| Flutter Impeller |

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

## Classes
class | BlendFilterContentsTest
struct | BlendModeSelection
struct | ColorBlendTestData
class | CompareFunctionUIData
struct | CVTest
class | FailingAllocator
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
struct | TextRenderOptions
class | VulkanScreenshotter
class | WorkingDirectory

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

## Functions
| TEST (AllocationSizeTest, CanCreateTypedAllocations)
| TEST (AllocationSizeTest, CanCreateTypedAllocationsWithLiterals)
| TEST (AllocationSizeTest, CanConvert)
| TEST (AllocationSizeTest, ConversionsAreNonTruncating)
| TEST (AllocationSizeTest, CanGetFloatValues)
| TEST (AllocationSizeTest, RelationalOperatorsAreFunctional)
| TEST (AllocationSizeTest, CanCast)
| TEST (AllocationSizeTest, CanPerformSimpleArithmetic)
| TEST (AllocationSizeTest, CanConstructWithArith)
| 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 (AllocatorTest, RangeTest)
| 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, DlAtlasGeometryNoBlend)
| TEST_P (AiksTest, DlAtlasGeometryBlend)
| TEST_P (AiksTest, DlAtlasGeometryColorButNoBlend)
| TEST_P (AiksTest, DlAtlasGeometrySkip)
| 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, CanRenderRoundedRectWithNonUniformRadii)
| TEST_P (AiksTest, CanDrawPaint)
| TEST_P (AiksTest, CanDrawPaintMultipleTimes)
| TEST_P (AiksTest, FilledCirclesRenderCorrectly)
| TEST_P (AiksTest, StrokedCirclesRenderCorrectly)
| TEST_P (AiksTest, FilledEllipsesRenderCorrectly)
| TEST_P (AiksTest, FilledRoundRectsRenderCorrectly)
| TEST_P (AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly)
| TEST_P (AiksTest, CanRenderClippedBackdropFilter)
| TEST_P (AiksTest, CanDrawPerspectiveTransformWithClips)
| TEST_P (AiksTest, ImageColorSourceEffectTransform)
| TEST_P (AiksTest, SubpassWithClearColorOptimization)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen)
| TEST_P (AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass)
| TEST_P (AiksTest, EmptySaveLayerIgnoresPaint)
| TEST_P (AiksTest, EmptySaveLayerRendersWithClear)
| TEST_P (AiksTest, CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated)
| TEST_P (AiksTest, FormatWideGamut)
| TEST_P (AiksTest, FormatSRGB)
| TEST_P (AiksTest, CoordinateConversionsAreCorrect)
| TEST_P (AiksTest, CanPerformFullScreenMSAA)
| TEST_P (AiksTest, CanPerformSkew)
| TEST_P (AiksTest, CanPerformSaveLayerWithBounds)
| 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, FastEllipticalRRectMaskBlursRenderCorrectly)
| TEST_P (AiksTest, PipelineBlendSingleParameter)
| TEST_P (AiksTest, MassiveScalingMatrixImageFilter)
static BlendModeSelection | GetBlendModeSelection ()
| 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, ColorFilterBlend)
| TEST_P (AiksTest, ColorFilterAdvancedBlend)
| TEST_P (AiksTest, ColorFilterAdvancedBlendNoFbFetch)
| TEST_P (AiksTest, BlendModePlusAlphaWideGamut)
| TEST_P (AiksTest, BlendModePlusAlphaColorFilterWideGamut)
| TEST_P (AiksTest, ForegroundBlendSubpassCollapseOptimization)
| TEST_P (AiksTest, ClearBlend)
static sk_sp< DisplayList > | BlendModeTest (Vector2 content_scale, BlendMode blend_mode, const sk_sp< DlImageImpeller > &src_image, const sk_sp< DlImageImpeller > &dst_image, Scalar src_alpha)
| TEST_P (AiksTest, CanDrawPaintMultipleTimesInteractive)
| TEST_P (AiksTest, ForegroundPipelineBlendAppliesTransformCorrectly)
| TEST_P (AiksTest, ForegroundAdvancedBlendAppliesTransformCorrectly)
| TEST_P (AiksTest, FramebufferAdvancedBlendCoverage)
| TEST_P (AiksTest, ColorWheel)
| TEST_P (AiksTest, SolidColorOvalsMaskBlurTinySigma)
sk_sp< flutter::DisplayList > | DoGradientOvalStrokeMaskBlur (Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlur)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurSigmaZero)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurOuter)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurInner)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurSolid)
| TEST_P (AiksTest, SolidColorCircleMaskBlurTinySigma)
| 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, MaskBlurWithZeroSigmaIsSkipped)
static sk_sp< DisplayList > | MaskBlurVariantTest (const AiksTest &test_context, const MaskBlurTestConfig &config)
| TEST_P (AiksTest, GaussianBlurStyleInner)
| TEST_P (AiksTest, GaussianBlurStyleOuter)
| TEST_P (AiksTest, GaussianBlurStyleSolid)
| TEST_P (AiksTest, MaskBlurTexture)
| TEST_P (AiksTest, MaskBlurDoesntStretchContents)
| TEST_P (AiksTest, GaussianBlurAtPeripheryVertical)
| TEST_P (AiksTest, GaussianBlurAtPeripheryHorizontal)
| TEST_P (AiksTest, GaussianBlurAnimatedBackdrop)
| TEST_P (AiksTest, GaussianBlurStyleInnerGradient)
| TEST_P (AiksTest, GaussianBlurStyleSolidGradient)
| TEST_P (AiksTest, GaussianBlurStyleOuterGradient)
| TEST_P (AiksTest, GaussianBlurScaledAndClipped)
| TEST_P (AiksTest, GaussianBlurRotatedAndClippedInteractive)
| TEST_P (AiksTest, GaussianBlurOneDimension)
| TEST_P (AiksTest, GaussianBlurRotatedAndClipped)
| TEST_P (AiksTest, GaussianBlurRotatedNonUniform)
| TEST_P (AiksTest, BlurredRectangleWithShader)
| TEST_P (AiksTest, GaussianBlurWithoutDecalSupport)
| TEST_P (AiksTest, GaussianBlurSolidColorTinyMipMap)
| TEST_P (AiksTest, GaussianBlurBackdropTinyMipMap)
| 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, 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)
| TEST_P (AiksTest, CanRenderClippedRuntimeEffects)
| TEST_P (AiksTest, DrawPaintTransformsBounds)
bool | RenderTextInCanvasSkia (const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string_view &font_fixture, const TextRenderOptions &options={})
bool | RenderTextInCanvasSTB (const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string &font_fixture, const TextRenderOptions &options={})
| TEST_P (AiksTest, CanRenderTextFrame)
| TEST_P (AiksTest, CanRenderTextFrameWithInvertedTransform)
| TEST_P (AiksTest, CanRenderStrokedTextFrame)
| TEST_P (AiksTest, CanRenderTextStrokeWidth)
| 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, DrawScaledTextWithPerspectiveNoSaveLayer)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveSaveLayer)
| TEST_P (AiksTest, CanRenderTextWithLargePerspectiveTransform)
| TEST_P (AiksTest, CanRenderTextWithPerspectiveTransformInSublist)
| TEST_P (AiksTest, TextForegroundShaderWithTransform)
| 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, 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, CanRenderDestructiveSaveLayer)
| TEST_P (AiksTest, CanDrawPoints)
| TEST_P (AiksTest, CanDrawPointsWithTextureMap)
| TEST_P (AiksTest, MipmapGenerationWorksCorrectly)
| TEST_P (AiksTest, StrokedPathWithMoveToThenCloseDrawnCorrectly)
| TEST_P (AiksTest, SetContentsWithRegion)
| TEST_P (AiksTest, ReleasesTextureOnTeardown)
| TEST_P (AiksTest, MatrixImageFilterMagnify)
| TEST_P (AiksTest, ImageFilteredSaveLayerWithUnboundedContents)
| TEST_P (AiksTest, MatrixBackdropFilter)
| TEST_P (AiksTest, MatrixSaveLayerFilter)
| TEST_P (AiksTest, CanDrawScaledPointsSmallScaleLargeRadius)
| TEST_P (AiksTest, CanDrawScaledPointsLargeScaleSmallRadius)
| TEST_P (AiksTest, TransparentShadowProducesCorrectColor)
| TEST_P (AiksTest, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists)
| TEST_P (AiksTest, BackdropRestoreUsesCorrectCoverageForFirstRestoredClip)
| TEST_P (AiksTest, CanPictureConvertToImage)
| TEST_P (AiksTest, CanEmptyPictureConvertToImage)
| 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, DrawVerticesWithInvalidIndices)
| TEST_P (AiksTest, DrawVerticesTextureCoordinatesWithFragmentShader)
| TEST_P (AiksTest, DrawVerticesTextureCoordinatesWithFragmentShaderNonZeroOrigin)
| INSTANTIATE_PLAYGROUND_SUITE (AiksTest)
std::unique_ptr< Canvas > | CreateTestCanvas (ContentContext &context, std::optional< Rect > cull_rect=std::nullopt)
| TEST_P (AiksTest, TransformMultipliesCorrectly)
| TEST_P (AiksTest, CanvasCanPushPopCTM)
| TEST_P (AiksTest, CanvasCTMCanBeUpdated)
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, 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)
| TEST_P (DisplayListTest, DrawPaintIgnoresMaskFilter)
| TEST_P (DisplayListTest, DrawMaskBlursThatMightUseSaveLayers)
| TEST (SkiaConversionTest, ToMatrixTranslate)
| TEST (SkiaConversionTest, ToMatrixScale)
| TEST (SkiaConversionTest, ToMatrixRotate)
| TEST (SkiaConversionTest, ToMatrixSkew)
| TEST (SkiaConversionTest, ToSamplerDescriptor)
| 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 (SkiaConversionsTest, BlendMode)
| 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 (HostBufferTest, EmplaceWithFailingAllocationDoesntCrash)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipeline)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithNoClips)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithClips)
| TEST (DrawOrderResolverTest, GetSortedDrawsRespectsSkipCounts)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithFlush)
| 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, AppendLargerClipCoverage)
| TEST (EntityPassClipStackTest, AppendLargerClipCoverageWithDifferenceOrNonSquare)
| TEST (EntityPassClipStackTest, AppendDecreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, AppendIncreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, UnbalancedRestore)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpasses)
| TEST_P (EntityTest, CanCreateEntity)
| TEST_P (EntityTest, FilterCoverageRespectsCropRect)
| 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, 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, 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, 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_P (EntityTest, DrawSuperEllipse)
| TEST_P (EntityTest, SolidColorApplyColorFilter)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Linear)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Radial)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Conical)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Sweep)
| TEST (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 (SaveLayerUtilsTest, SimplePaintComputedCoverage)
| TEST (SaveLayerUtilsTest, BackdropFiterComputedCoverage)
| TEST (SaveLayerUtilsTest, ImageFiterComputedCoverage)
| TEST (SaveLayerUtilsTest, ImageFiterSmallScaleComputedCoverageLargerThanBoundsLimit)
| TEST (SaveLayerUtilsTest, ImageFiterLargeScaleComputedCoverageLargerThanBoundsLimit)
| TEST (SaveLayerUtilsTest, DisjointCoverage)
| TEST (SaveLayerUtilsTest, DisjointCoverageTransformedByImageFilter)
| TEST (SaveLayerUtilsTest, DisjointCoveragTransformedByCTM)
| TEST (SaveLayerUtilsTest, BasicEmptyCoverage)
| TEST (SaveLayerUtilsTest, ImageFilterEmptyCoverage)
| TEST (SaveLayerUtilsTest, BackdropFilterEmptyCoverage)
| TEST (SaveLayerUtilsTest, FloodInputCoverage)
| TEST (SaveLayerUtilsTest, FloodInputCoverageWithImageFilter)
| TEST (SaveLayerUtilsTest, FloodInputCoverageWithImageFilterWithNoCoverageProducesNoCoverage)
| TEST (SaveLayerUtilsTest, CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageSmallerWithImageFilter)
| TEST (SaveLayerUtilsTest, CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageLargerWithImageFilter)
| TEST (SaveLayerUtilsTest, CoverageLimitRespectedIfSubstantiallyDifferentFromContentCoverge)
| 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, 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, Equals)
| TEST (MatrixTest, NotEquals)
| TEST (MatrixTest, HasPerspective2D)
| TEST (MatrixTest, HasPerspective)
| TEST (MatrixTest, HasTranslation)
| TEST (MatrixTest, IsAligned2D)
| TEST (MatrixTest, IsAligned)
| TEST (MatrixTest, TransformHomogenous)
| TEST (MatrixTest, GetMaxBasisXYNegativeScale)
| TEST (MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactor)
| TEST (MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactorNonScaleTranslate)
| TEST (MatrixTest, TranslateWithPerspective)
| TEST (PathTest, CubicPathComponentPolylineDoesNotIncludePointOne)
| TEST (PathTest, EmptyPathWithContour)
| 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, RectSimpleWH)
| TEST (RectTest, IRectSimpleWH)
| 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, ThreadLocalCleanupDeletesCommandPool)
| 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 (DriverInfoVKTest, CanIdentifyBadMaleoonDriver)
bool | IsBadVersionTest (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, DriverParsingMali)
| TEST (DriverInfoVKTest, DriverParsingArm)
| TEST (DriverInfoVKTest, DisabledDevices)
| TEST (DriverInfoVKTest, EnabledDevicesMali)
| TEST (DriverInfoVKTest, EnabledDevicesAdreno)
| TEST (FenceWaiterVKTest, IgnoresNullFence)
| TEST (FenceWaiterVKTest, IgnoresNullCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
| TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
| TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
| TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
| TEST (PipelineCacheDataVKTest, CanTestHeaderCompatibility)
| TEST (PipelineCacheDataVKTest, CanCreateFromDeviceProperties)
| TEST_P (PipelineCacheDataVKPlaygroundTest, CanPersistAndRetrievePipelineCache)
| TEST_P (PipelineCacheDataVKPlaygroundTest, IntegrityChecksArePerformedOnPersistedData)
| 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)
| TEST_P (BlitPassTest, CanResizeTextures)
| 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)
| CAPABILITY_TEST (SupportsTriangleFan, false)
| TEST (CapabilitiesTest, DefaultColorFormat)
| TEST (CapabilitiesTest, DefaultStencilFormat)
| TEST (CapabilitiesTest, DefaultDepthStencilFormat)
| TEST (CapabilitiesTest, DefaultGlyphAtlasFormat)
| TEST (CapabilitiesTest, MaxRenderPassAttachmentSize)
| 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
static constexpr const size_t | kMagicFailingAllocation = 1024000 * 2
std::vector< Point > | golden_cubic_and_quad_points

## Typedef Documentation

## ◆ 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 19 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 13 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 16 of file host_buffer_unittests.cc.

## ◆ PipelineCacheDataVKPlaygroundTest

using impeller::testing::PipelineCacheDataVKPlaygroundTest = typedef PlaygroundTest

Definition at line 95 of file pipeline_cache_data_vk_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.

## ◆ SaveLayerUtilsTest

using impeller::testing::SaveLayerUtilsTest = typedef ::testing::Test

Definition at line 15 of file save_layer_utils_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 sk_sp<DisplayList> impeller::testing::BlendModeTest | ( | Vector2 | content_scale,
|  | BlendMode | blend_mode,
|  | const sk_sp< DlImageImpeller > & | src_image,
|  | const sk_sp< DlImageImpeller > & | 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 501 of file aiks_dl_blend_unittests.cc.

505 {
506 if (AiksTest::ImGuiBegin("Controls", nullptr,
507 ImGuiWindowFlags_AlwaysAutoResize)) {
508 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
509 ImGui::End();
510 }
511
512 Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
513 auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
514 Color::LimeGreen().WithAlpha(0.75),
515 Color::Black().WithAlpha(0.75)});
516
517 DisplayListBuilder builder;
518 {
519 DlPaint paint;
520 paint.setColor(DlColor::kBlack());
521 builder.DrawPaint(paint);
522 }
523 // TODO(bdero): Why does this cause the left image to double scale on high DPI
524 // displays.
525 // builder.Scale(content_scale);
526
527 //----------------------------------------------------------------------------
528 /// 1. Save layer blending (top squares).
529 ///
530
531 builder.Save();
532 for (const auto& color : source_colors) {
533 builder.Save();
534 {
535 builder.ClipRect(SkRect::MakeXYWH(25, 25, 100, 100));
536 // Perform the blend in a SaveLayer so that the initial backdrop color is
537 // fully transparent black. SourceOver blend the result onto the parent
538 // pass.
539 builder.SaveLayer({});
540 {
541 DlPaint draw_paint;
542 draw_paint.setColor(
543 DlColor::RGBA(destination_color.red, destination_color.green,
544 destination_color.blue, destination_color.alpha));
545 builder.DrawPaint(draw_paint);
546
547 // Draw the source color in an offscreen pass and blend it to the parent
548 // pass.
549 DlPaint save_paint;
550 save_paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
551 builder.SaveLayer(nullptr, &save_paint);
552 { //
553 DlPaint paint;
554 paint.setColor(
555 DlColor::RGBA(color.red, color.green, color.blue, color.alpha));
556 builder.DrawRect(SkRect::MakeXYWH(25, 25, 100, 100), paint);
557 }
558 builder.Restore();
559 }
560 builder.Restore();
561 }
562 builder.Restore();
563 builder.Translate(100, 0);
564 }
565 builder.RestoreToCount(0);
566
567 //----------------------------------------------------------------------------
568 /// 2. CPU blend modes (bottom squares).
569 ///
570
571 builder.Save();
572 builder.Translate(0, 100);
573 // Perform the blend in a SaveLayer so that the initial backdrop color is
574 // fully transparent black. SourceOver blend the result onto the parent pass.
575 builder.SaveLayer({});
576 for (const auto& color : source_colors) {
577 // Simply write the CPU blended color to the pass.
578 DlPaint paint;
579 auto dest = destination_color.Blend(color, blend_mode);
580 paint.setColor(DlColor::RGBA(dest.red, dest.green, dest.blue, dest.alpha));
581 paint.setBlendMode(DlBlendMode::kSrcOver);
582 builder.DrawRect(SkRect::MakeXYWH(25, 25, 100, 100), paint);
583 builder.Translate(100, 0);
584 }
585 builder.Restore();
586 builder.Restore();
587
588 //----------------------------------------------------------------------------
589 /// 3. Image blending (bottom images).
590 ///
591 /// Compare these results with the images in the Flutter blend mode
592 /// documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html
593 ///
594
595 builder.Translate(0, 250);
596
597 // Draw grid behind the images.
598 {
599 DlPaint paint;
600 paint.setColor(DlColor::RGBA(41 / 255.0, 41 / 255.0, 41 / 255.0, 1));
601 builder.DrawRect(SkRect::MakeLTRB(0, 0, 800, 400), paint);
602 }
603
604 DlPaint square_paint;
605 square_paint.setColor(DlColor::RGBA(15 / 255.0, 15 / 255.0, 15 / 255.0, 1));
606 for (int y = 0; y < 400 / 8; y++) {
607 for (int x = 0; x < 800 / 16; x++) {
608 builder.DrawRect(SkRect::MakeXYWH(x * 16 + (y % 2) * 8, y * 8, 8, 8),
609 square_paint);
610 }
611 }
612
613 // Uploaded image source (left image).
614 DlPaint paint;
615 paint.setBlendMode(DlBlendMode::kSrcOver);
616 builder.Save();
617 builder.SaveLayer(nullptr, &paint);
618 {
619 builder.DrawImage(dst_image, {0, 0}, DlImageSampling::kMipmapLinear,
620 &paint);
621
622 paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
623 paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
624 builder.DrawImage(src_image, {0, 0}, DlImageSampling::kMipmapLinear,
625 &paint);
626 }
627 builder.Restore();
628 builder.Restore();
629
630 // Rendered image source (right image).
631 builder.Save();
632
633 DlPaint save_paint;
634 builder.SaveLayer(nullptr, &save_paint);
635 {
636 builder.DrawImage(dst_image, {400, 0}, DlImageSampling::kMipmapLinear,
637 nullptr);
638
639 DlPaint save_paint;
640 save_paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
641 save_paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
642 builder.SaveLayer(nullptr, &save_paint);
643 {
644 builder.DrawImage(src_image, {400, 0}, DlImageSampling::kMipmapLinear,
645 nullptr);
646 }
647 builder.Restore();
648 }
649 builder.Restore();
650 builder.Restore();
651
652 return builder.Build();
653 }

References impeller::Color::alpha, impeller::Color::Black(), impeller::Color::Blend(), impeller::Color::blue, color, impeller::Color::CornflowerBlue(), impeller::Color::green, impeller::AiksPlayground::ImGuiBegin(), impeller::Color::LimeGreen(), impeller::Color::red, 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(), 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().

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(), 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(), impeller::Color::ToARGB(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by TEST_P().

## ◆ CAPABILITY_TEST() [1/10]

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

## ◆ CAPABILITY_TEST() [2/10]

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

## ◆ CAPABILITY_TEST() [3/10]

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

## ◆ CAPABILITY_TEST() [4/10]

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

## ◆ CAPABILITY_TEST() [5/10]

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

## ◆ CAPABILITY_TEST() [6/10]

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

## ◆ CAPABILITY_TEST() [7/10]

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

## ◆ CAPABILITY_TEST() [8/10]

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

## ◆ CAPABILITY_TEST() [9/10]

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

## ◆ CAPABILITY_TEST() [10/10]

impeller::testing::CAPABILITY_TEST | ( | SupportsTriangleFan | ,
|  | 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().

## ◆ 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().

## ◆ CreateTestCanvas()

std::unique_ptr<Canvas> impeller::testing::CreateTestCanvas | ( | ContentContext & | context,
|  | std::optional< Rect > | cull_rect = `std::nullopt`
| ) |  |

Definition at line 13 of file canvas_unittests.cc.

15 {
16 RenderTarget render_target = context.GetRenderTargetCache()->CreateOffscreen(
17 *context.GetContext(), {1, 1}, 1);
18
19 if (cull_rect.has_value()) {
20 return std::make_unique<Canvas>(context, render_target, false,
21 cull_rect.value());
22 }
23 return std::make_unique<Canvas>(context, render_target, false);
24 }

References impeller::ContentContext::GetContext(), and impeller::ContentContext::GetRenderTargetCache().

Referenced by TEST_P().

## ◆ CreateTestYUVTextures()

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

Definition at line 1659 of file entity_unittests.cc.

1661 {
1662 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
1663 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
1664 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
1665 Vector3 white = {1.0, 1.0, 1.0};
1666 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
1667 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
1668 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
1669 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
1670 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
1671 std::vector<uint8_t> y_data;
1672 std::vector<uint8_t> uv_data;
1673 for (int i = 0; i < 4; i++) {
1674 auto yuv = yuvs[i];
1675 uint8_t y = std::round(yuv.x * 255.0);
1676 uint8_t u = std::round(yuv.y * 255.0);
1677 uint8_t v = std::round(yuv.z * 255.0);
1678 for (int j = 0; j < 16; j++) {
1679 y_data.push_back(y);
1680 }
1681 for (int j = 0; j < 8; j++) {
1682 uv_data.push_back(j % 2 == 0 ? u : v);
1683 }
1684 }
1685 auto cmd_buffer = context->CreateCommandBuffer();
1686 auto blit_pass = cmd_buffer->CreateBlitPass();
1687
1688 impeller::TextureDescriptor y_texture_descriptor;
1689 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1690 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
1691 y_texture_descriptor.size = {8, 8};
1692 auto y_texture =
1693 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
1694 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
1695 auto y_mapping_buffer =
1696 context->GetResourceAllocator()->CreateBufferWithCopy(*y_mapping);
1697
1698 blit_pass->AddCopy(DeviceBuffer::AsBufferView(y_mapping_buffer), y_texture);
1699
1700 impeller::TextureDescriptor uv_texture_descriptor;
1701 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1702 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
1703 uv_texture_descriptor.size = {4, 4};
1704 auto uv_texture =
1705 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
1706 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
1707 auto uv_mapping_buffer =
1708 context->GetResourceAllocator()->CreateBufferWithCopy(*uv_mapping);
1709
1710 blit_pass->AddCopy(DeviceBuffer::AsBufferView(uv_mapping_buffer), uv_texture);
1711
1712 if (!blit_pass->EncodeCommands(context->GetResourceAllocator()) ||
1713 !context->GetCommandQueue()->Submit({cmd_buffer}).ok()) {
1714 FML_DLOG(ERROR) << "Could not copy contents into Y/UV texture.";
1715 }
1716
1717 return {y_texture, uv_texture};
1718 }

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

## ◆ DoGradientOvalStrokeMaskBlur()

sk_sp<flutter::DisplayList> impeller::testing::DoGradientOvalStrokeMaskBlur | ( | Vector2 | content_Scale,
|  | Scalar | sigma,
|  | DlBlurStyle | style
| ) |  |

Definition at line 63 of file aiks_dl_blur_unittests.cc.

65 {
66 DisplayListBuilder builder;
67 builder.Scale(content_Scale.x, content_Scale.y);
68
69 DlPaint background_paint;
70 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
71 builder.DrawPaint(background_paint);
72
73 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
74 std::vector<Scalar> stops = {0.0, 1.0};
75
76 DlPaint paint;
77 paint.setMaskFilter(DlBlurMaskFilter::Make(style, sigma));
78 auto gradient = DlColorSource::MakeLinear(
79 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
80 paint.setColorSource(gradient);
81 paint.setColor(DlColor::kWhite());
82 paint.setDrawStyle(DlDrawStyle::kStroke);
83 paint.setStrokeWidth(20);
84
85 builder.Save();
86 builder.Translate(100, 100);
87
88 {
89 DlPaint line_paint;
90 line_paint.setColor(DlColor::kWhite());
91 builder.DrawLine({100, 0}, {100, 60}, line_paint);
92 builder.DrawLine({0, 30}, {200, 30}, line_paint);
93 }
94
95 SkRRect rrect =
96 SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 200.0f, 60.0f), 50, 100);
97 builder.DrawRRect(rrect, paint);
98 builder.Restore();
99
100 return builder.Build();
101 }

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

Referenced by TEST_P().

## ◆ flip_lr()

template<typename R >

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

Definition at line 1310 of file rect_unittests.cc.

1310 {
1311 return R::MakeLTRB(rect.GetRight(), rect.GetTop(), //
1312 rect.GetLeft(), rect.GetBottom());
1313 }

Referenced by flip_lrtb(), and TEST().

## ◆ flip_lrtb()

template<typename R >

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

Definition at line 1322 of file rect_unittests.cc.

1322 {
1323 return flip_lr(flip_tb(rect));
1324 }

References flip_lr(), and flip_tb().

Referenced by TEST().

## ◆ flip_tb()

template<typename R >

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

Definition at line 1316 of file rect_unittests.cc.

1316 {
1317 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(), //
1318 rect.GetRight(), rect.GetTop());
1319 }

Referenced by flip_lrtb(), and TEST().

## ◆ GetBlendModeSelection()

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

Definition at line 45 of file aiks_dl_blend_unittests.cc.

45 {
46 std::vector<const char*> blend_mode_names;
47 std::vector<BlendMode> blend_mode_values;
48 {
49 const std::vector<std::tuple<const char*, BlendMode>> blends = {
50 IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_TUPLE)};
51 assert(blends.size() ==
52 static_cast<size_t>(Entity::kLastAdvancedBlendMode) + 1);
53 for (const auto& [name, mode] : blends) {
54 blend_mode_names.push_back(name);
55 blend_mode_values.push_back(mode);
56 }
57 }
58
59 return {blend_mode_names, blend_mode_values};
60 }

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

Referenced by TEST_P().

## ◆ 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().

## ◆ IsBadVersionTest()

bool impeller::testing::IsBadVersionTest | ( | std::string_view | driver_name,
|  | bool | qc = `true`
| ) |  |

Definition at line 52 of file driver_info_vk_unittests.cc.

52 {
53 auto const context =
54 MockVulkanContextBuilder()
55 .SetPhysicalPropertiesCallback(
56 [&driver_name, qc](VkPhysicalDevice device,
57 VkPhysicalDeviceProperties* prop) {
58 if (qc) {
59 prop->vendorID = 0x168C; // Qualcomm
60 } else {
61 prop->vendorID = 0x13B5; // ARM
62 }
63 driver_name.copy(prop->deviceName, driver_name.size());
64 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
65 })
66 .Build();
67 return context->GetDriverInfo()->IsKnownBadDriver();
68 }

Referenced by TEST().

## ◆ MaskBlurVariantTest()

static sk_sp<DisplayList> impeller::testing::MaskBlurVariantTest | ( | const AiksTest & | test_context,
|  | const MaskBlurTestConfig & | config
| ) |  |
| static

Definition at line 403 of file aiks_dl_blur_unittests.cc.

405 {
406 DisplayListBuilder builder;
407 builder.Scale(test_context.GetContentScale().x,
408 test_context.GetContentScale().y);
409 builder.Scale(0.8f, 0.8f);
410 builder.Translate(50.f, 50.f);
411
412 DlPaint draw_paint;
413 draw_paint.setColor(
414 DlColor::RGBA(Color::AntiqueWhite().red, Color::AntiqueWhite().green,
415 Color::AntiqueWhite().blue, Color::AntiqueWhite().alpha));
416 builder.DrawPaint(draw_paint);
417
418 DlPaint paint;
419 paint.setMaskFilter(DlBlurMaskFilter::Make(config.style, config.sigma));
420 paint.setInvertColors(config.invert_colors);
421 paint.setImageFilter(config.image_filter);
422 paint.setBlendMode(config.blend_mode);
423
424 const Scalar x = 50;
425 const Scalar radius = 20.0f;
426 const Scalar y_spacing = 100.0f;
427 Scalar alpha = config.alpha * 255;
428
429 Scalar y = 50;
430 paint.setColor(DlColor::kCrimson().withAlpha(alpha));
431 builder.DrawRect(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
432 radius, 60.0f - radius),
433 paint);
434
435 y += y_spacing;
436 paint.setColor(DlColor::kBlue().withAlpha(alpha));
437 builder.DrawCircle({x + 25, y + 25}, radius, paint);
438
439 y += y_spacing;
440 paint.setColor(DlColor::kGreen().withAlpha(alpha));
441 builder.DrawOval(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
442 radius, 60.0f - radius),
443 paint);
444
445 y += y_spacing;
446 paint.setColor(DlColor::kPurple().withAlpha(alpha));
447 SkRRect rrect =
448 SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, radius);
449 builder.DrawRRect(rrect, paint);
450
451 y += y_spacing;
452 paint.setColor(DlColor::kOrange().withAlpha(alpha));
453
454 rrect =
455 SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, 5.0);
456 builder.DrawRRect(rrect, paint);
457
458 y += y_spacing;
459 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
460
461 {
462 SkPath path;
463 path.moveTo(x + 0, y + 60);
464 path.lineTo(x + 30, y + 0);
465 path.lineTo(x + 60, y + 60);
466 path.close();
467
468 builder.DrawPath(path, paint);
469 }
470
471 y += y_spacing;
472 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
473 {
474 SkPath path;
475 path.addArc(SkRect::MakeXYWH(x + 5, y, 50, 50), 90, 180);
476 path.addArc(SkRect::MakeXYWH(x + 25, y, 50, 50), 90, 180);
477 path.close();
478 builder.DrawPath(path, paint);
479 }
480
481 return builder.Build();
482 }

References impeller::testing::MaskBlurTestConfig::alpha, impeller::Color::AntiqueWhite(), impeller::testing::MaskBlurTestConfig::blend_mode, impeller::Playground::GetContentScale(), impeller::testing::MaskBlurTestConfig::image_filter, impeller::testing::MaskBlurTestConfig::invert_colors, impeller::testing::MaskBlurTestConfig::sigma, impeller::testing::MaskBlurTestConfig::style, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ RenderTextInCanvasSkia()

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

Definition at line 41 of file aiks_dl_text_unittests.cc.

45 {}) {
46 // Draw the baseline.
47 DlPaint paint;
48 paint.setColor(DlColor::kAqua().withAlpha(255 * 0.25));
49 canvas.DrawRect(SkRect::MakeXYWH(options.position.x() - 50,
50 options.position.y(), 900, 10),
51 paint);
52
53 // Mark the point at which the text is drawn.
54 paint.setColor(DlColor::kRed().withAlpha(255 * 0.25));
55 canvas.DrawCircle(options.position, 5.0, paint);
56
57 // Construct the text blob.
58 auto c_font_fixture = std::string(font_fixture);
59 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
60 if (!mapping) {
61 return false;
62 }
63 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
64 SkFont sk_font(font_mgr->makeFromData(mapping), options.font_size);
65 auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
66 if (!blob) {
67 return false;
68 }
69
70 // Create the Impeller text frame and draw it at the designated baseline.
71 auto frame = MakeTextFrameFromTextBlobSkia(blob);
72
73 DlPaint text_paint;
74 text_paint.setColor(options.color);
75 text_paint.setMaskFilter(options.filter);
76 text_paint.setStrokeWidth(options.stroke_width);
77 text_paint.setDrawStyle(options.stroke ? DlDrawStyle::kStroke
78 : DlDrawStyle::kFill);
79 canvas.DrawTextFrame(frame, options.position.x(), options.position.y(),
80 text_paint);
81 return true;
82 }

Referenced by flutter::testing::TEST_P(), and TEST_P().

## ◆ RenderTextInCanvasSTB()

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

Definition at line 84 of file aiks_dl_text_unittests.cc.

88 {}) {
89 // Draw the baseline.
90 DlPaint paint;
91 paint.setColor(DlColor::kAqua().withAlpha(255 * 0.25));
92 canvas.DrawRect(SkRect::MakeXYWH(options.position.x() - 50,
93 options.position.y(), 900, 10),
94 paint);
95
96 // Mark the point at which the text is drawn.
97 paint.setColor(DlColor::kRed().withAlpha(255 * 0.25));
98 canvas.DrawCircle(options.position, 5.0, paint);
99
100 // Construct the text blob.
101 auto mapping = flutter::testing::OpenFixtureAsMapping(font_fixture.c_str());
102 if (!mapping) {
103 return false;
104 }
105 auto typeface_stb = std::make_shared<TypefaceSTB>(std::move(mapping));
106
107 auto frame = MakeTextFrameSTB(
108 typeface_stb, Font::Metrics{.point_size = options.font_size}, text);
109
110 DlPaint text_paint;
111 text_paint.setColor(options.color);
112
113 canvas.DrawTextFrame(frame, options.position.x(), options.position.y(),
114 text_paint);
115 return true;
116 }

Referenced by TEST_P().

## ◆ RGBToYUV()

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

Definition at line 1642 of file entity_unittests.cc.

1642 {
1643 Vector3 yuv;
1644 switch (yuv_color_space) {
1645 case YUVColorSpace::kBT601FullRange:
1646 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
1647 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
1648 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
1649 break;
1650 case YUVColorSpace::kBT601LimitedRange:
1651 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
1652 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
1653 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
1654 break;
1655 }
1656 return yuv;
1657 }

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

Definition at line 1336 of file rect_unittests.cc.

1336 {
1337 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1338 FML_DCHECK(index >= 0 && index <= 3);
1339 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.x;
1340 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.y;
1341 return Point(x, y);
1342 }

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

Definition at line 1326 of file rect_unittests.cc.

1326 {
1327 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1328 FML_DCHECK(index >= 0 && index <= 15);
1329 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.GetLeft();
1330 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.GetTop();
1331 Scalar r = ((index & (1 << 2)) != 0) ? nan : rect.GetRight();
1332 Scalar b = ((index & (1 << 3)) != 0) ? nan : rect.GetBottom();
1333 return Rect::MakeLTRB(l, t, r, b);
1334 }

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

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanCast |
| ) |  |

Definition at line 77 of file allocation_size_unittests.cc.

77 {
78 using namespace allocation_size_literals;
79 {
80 auto a = KiloBytes{1500_bytes};
81 ASSERT_DOUBLE_EQ(a.GetSize(), 1.5);
82 }
83 {
84 auto a = KiloBytes{Bytes{1500}};
85 ASSERT_DOUBLE_EQ(a.GetSize(), 1.5);
86 }
87
88 ASSERT_DOUBLE_EQ(MebiBytes{Bytes{4194304}}.GetSize(), 4);
89 }

References impeller::AllocationSize< Period >::GetSize().

## ◆ TEST() [2/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanConstructWithArith |
| ) |  |

Definition at line 110 of file allocation_size_unittests.cc.

110 {
111 {
112 Bytes a(1u);
113 ASSERT_EQ(a.GetByteSize(), 1u);
114 }
115 {
116 Bytes a(1.5);
117 ASSERT_EQ(a.GetByteSize(), 2u);
118 }
119 {
120 Bytes a(1.5f);
121 ASSERT_EQ(a.GetByteSize(), 2u);
122 }
123 }

References impeller::AllocationSize< Period >::GetByteSize().

## ◆ TEST() [3/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanConvert |
| ) |  |

Definition at line 44 of file allocation_size_unittests.cc.

44 {
45 using namespace allocation_size_literals;
46 ASSERT_EQ((5_gb).ConvertTo<MegaBytes>().GetSize(), 5000u);
47 }

## ◆ TEST() [4/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanCreateTypedAllocations |
| ) |  |

Definition at line 10 of file allocation_size_unittests.cc.

10 {
11 auto bytes = Bytes{1024};
12 ASSERT_EQ(bytes.GetByteSize(), 1024u);
13
14 auto kilobytes = KiloBytes{5};
15 ASSERT_EQ(kilobytes.GetByteSize(), 5u * 1e3);
16
17 auto megabytes = MegaBytes{5};
18 ASSERT_EQ(megabytes.GetByteSize(), 5u * 1e6);
19
20 auto gigabytes = GigaBytes{5};
21 ASSERT_EQ(gigabytes.GetByteSize(), 5u * 1e9);
22
23 auto kibibytes = KibiBytes{1};
24 ASSERT_EQ(kibibytes.GetByteSize(), 1024u);
25
26 auto mebibytes = MebiBytes{1};
27 ASSERT_EQ(mebibytes.GetByteSize(), 1048576u);
28
29 auto gigibytes = GibiBytes{1};
30 ASSERT_EQ(gigibytes.GetByteSize(), 1073741824u);
31 }

## ◆ TEST() [5/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanCreateTypedAllocationsWithLiterals |
| ) |  |

Definition at line 33 of file allocation_size_unittests.cc.

33 {
34 using namespace allocation_size_literals;
35 ASSERT_EQ((1024_bytes).GetByteSize(), 1024u);
36 ASSERT_EQ((5_kb).GetByteSize(), 5u * 1e3);
37 ASSERT_EQ((5_mb).GetByteSize(), 5u * 1e6);
38 ASSERT_EQ((5_gb).GetByteSize(), 5u * 1e9);
39 ASSERT_EQ((1_kib).GetByteSize(), 1024u);
40 ASSERT_EQ((1_mib).GetByteSize(), 1048576u);
41 ASSERT_EQ((1_gib).GetByteSize(), 1073741824u);
42 }

## ◆ TEST() [6/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanGetFloatValues |
| ) |  |

Definition at line 55 of file allocation_size_unittests.cc.

55 {
56 using namespace allocation_size_literals;
57 ASSERT_DOUBLE_EQ((1500_bytes).ConvertTo<KiloBytes>().GetSize(), 1.5);
58 }

## ◆ TEST() [7/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanPerformSimpleArithmetic |
| ) |  |

Definition at line 91 of file allocation_size_unittests.cc.

91 {
92 using namespace allocation_size_literals;
93 {
94 auto a = 100_bytes;
95 auto b = 200_bytes;
96 ASSERT_EQ((a + b).GetByteSize(), 300u);
97 }
98 {
99 auto a = 100_bytes;
100 a += 200_bytes;
101 ASSERT_EQ(a.GetByteSize(), 300u);
102 }
103 {
104 auto a = 100_bytes;
105 a -= 50_bytes;
106 ASSERT_EQ(a.GetByteSize(), 50u);
107 }
108 }

References impeller::saturated::b.

## ◆ TEST() [8/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | ConversionsAreNonTruncating |
| ) |  |

Definition at line 49 of file allocation_size_unittests.cc.

49 {
50 using namespace allocation_size_literals;
51 ASSERT_DOUBLE_EQ((1500_bytes).ConvertTo<KiloBytes>().GetSize(), 1.5);
52 ASSERT_EQ((1500_bytes).ConvertTo<KiloBytes>().GetByteSize(), 1500u);
53 }

## ◆ TEST() [9/389]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | RelationalOperatorsAreFunctional |
| ) |  |

Definition at line 60 of file allocation_size_unittests.cc.

60 {
61 using namespace allocation_size_literals;
62
63 auto a = 1500_bytes;
64 auto b = 2500_bytes;
65 auto c = 0_bytes;
66
67 ASSERT_TRUE(a != b);
68 ASSERT_FALSE(a == b);
69 ASSERT_TRUE(b > a);
70 ASSERT_TRUE(b >= a);
71 ASSERT_TRUE(a < b);
72 ASSERT_TRUE(a <= b);
73 ASSERT_TRUE(a);
74 ASSERT_FALSE(c);
75 }

References impeller::saturated::b.

## ◆ TEST() [10/389]

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

Definition at line 82 of file allocator_unittests.cc.

82 {
83 {
84 Range a = Range{0, 10};
85 Range b = Range{10, 20};
86 auto merged = a.Merge(b);
87
88 EXPECT_EQ(merged.offset, 0u);
89 EXPECT_EQ(merged.length, 30u);
90 }
91
92 {
93 Range a = Range{0, 10};
94 Range b = Range{100, 20};
95 auto merged = a.Merge(b);
96
97 EXPECT_EQ(merged.offset, 0u);
98 EXPECT_EQ(merged.length, 120u);
99 }
100
101 {
102 Range a = Range{0, 10};
103 Range b = Range{100, 20};
104 auto merged = b.Merge(a);
105
106 EXPECT_EQ(merged.offset, 0u);
107 EXPECT_EQ(merged.length, 120u);
108 }
109
110 {
111 Range a = Range{0, 10};
112 Range b = Range{100, 0};
113 auto merged = b.Merge(a);
114
115 EXPECT_EQ(merged.offset, 0u);
116 EXPECT_EQ(merged.length, 10u);
117 }
118
119 {
120 Range a = Range{0, 10};
121 Range b = Range{0, 10};
122 auto merged = b.Merge(a);
123
124 EXPECT_EQ(merged.offset, 0u);
125 EXPECT_EQ(merged.length, 10u);
126 }
127 }

References impeller::saturated::b, and impeller::Range::Merge().

## ◆ TEST() [11/389]

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() [12/389]

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

Definition at line 36 of file allocator_vk_unittests.cc.

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

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [13/389]

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

Definition at line 51 of file allocator_vk_unittests.cc.

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

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [14/389]

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

Definition at line 17 of file allocator_vk_unittests.cc.

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

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

## ◆ TEST() [15/389]

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

Definition at line 264 of file base_unittests.cc.

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

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

## ◆ TEST() [16/389]

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

Definition at line 255 of file base_unittests.cc.

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

## ◆ TEST() [17/389]

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

Definition at line 248 of file base_unittests.cc.

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

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

## ◆ TEST() [18/389]

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

Definition at line 32 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [19/389]

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

Definition at line 50 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [20/389]

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

Definition at line 60 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [21/389]

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

Definition at line 41 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [22/389]

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

Definition at line 69 of file capabilities_unittests.cc.

69 {
70 auto defaults = CapabilitiesBuilder().Build();
71 EXPECT_EQ(defaults->GetMaximumRenderPassAttachmentSize(), ISize(1, 1));
72 auto mutated = CapabilitiesBuilder()
73 .SetMaximumRenderPassAttachmentSize({100, 100})
74 .Build();
75 EXPECT_EQ(mutated->GetMaximumRenderPassAttachmentSize(), ISize(100, 100));
76 }

References impeller::CapabilitiesBuilder::Build(), and impeller::CapabilitiesBuilder::SetMaximumRenderPassAttachmentSize().

## ◆ TEST() [23/389]

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

Definition at line 214 of file context_vk_unittests.cc.

215 {
216 ScopedValidationDisable disable_validation;
217 const std::shared_ptr<ContextVK> context =
218 MockVulkanContextBuilder()
219 .SetPhysicalDeviceFormatPropertiesCallback(
220 [](VkPhysicalDevice physicalDevice, VkFormat format,
221 VkFormatProperties* pFormatProperties) {
222 if (format == VK_FORMAT_R8G8B8A8_UNORM) {
223 pFormatProperties->optimalTilingFeatures =
224 static_cast<VkFormatFeatureFlags>(
225 vk::FormatFeatureFlagBits::eColorAttachment);
226 }
227 // Ignore combined depth-stencil formats.
228 })
229 .Build();
230 ASSERT_EQ(context, nullptr);
231 }

## ◆ TEST() [24/389]

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

Definition at line 183 of file context_vk_unittests.cc.

183 {
184 const std::shared_ptr<ContextVK> context =
185 MockVulkanContextBuilder()
186 .SetPhysicalDeviceFormatPropertiesCallback(
187 [](VkPhysicalDevice physicalDevice, VkFormat format,
188 VkFormatProperties* pFormatProperties) {
189 if (format == VK_FORMAT_R8G8B8A8_UNORM) {
190 pFormatProperties->optimalTilingFeatures =
191 static_cast<VkFormatFeatureFlags>(
192 vk::FormatFeatureFlagBits::eColorAttachment);
193 } else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
194 pFormatProperties->optimalTilingFeatures =
195 static_cast<VkFormatFeatureFlags>(
196 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
197 }
198 // Ignore just the stencil format.
199 })
200 .Build();
201 ASSERT_NE(context, nullptr);
202 const CapabilitiesVK* capabilites_vk =
203 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
204 ASSERT_EQ(capabilites_vk->GetDefaultDepthStencilFormat(),
205 PixelFormat::kD32FloatS8UInt);
206 ASSERT_EQ(capabilites_vk->GetDefaultStencilFormat(),
207 PixelFormat::kD32FloatS8UInt);
208 }

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

## ◆ TEST() [25/389]

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

Definition at line 37 of file command_encoder_vk_unittests.cc.

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

References impeller::CommandBuffer::kCompleted.

## ◆ TEST() [26/389]

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

Definition at line 15 of file command_encoder_vk_unittests.cc.

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

## ◆ TEST() [27/389]

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() [28/389]

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() [29/389]

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() [30/389]

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() [31/389]

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

Definition at line 203 of file base_unittests.cc.

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

References impeller::ConditionVariable::Wait().

## ◆ TEST() [32/389]

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

Definition at line 158 of file base_unittests.cc.

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

References impeller::ConditionVariable::WaitFor().

## ◆ TEST() [33/389]

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

Definition at line 120 of file base_unittests.cc.

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

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

## ◆ TEST() [34/389]

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

Definition at line 141 of file base_unittests.cc.

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

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

## ◆ TEST() [35/389]

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

Definition at line 97 of file base_unittests.cc.

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

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

## ◆ TEST() [36/389]

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

Definition at line 151 of file context_vk_unittests.cc.

151 {
152 // The mocked methods don't report the presence of a validation layer but we
153 // explicitly ask for validation. Context creation should continue anyway.
154 auto context = MockVulkanContextBuilder()
155 .SetSettingsCallback([](auto& settings) {
156 settings.enable_validation = true;
157 })
158 .Build();
159 ASSERT_NE(context, nullptr);
160 const CapabilitiesVK* capabilites_vk =
161 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
162 ASSERT_FALSE(capabilites_vk->AreValidationsEnabled());
163 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [37/389]

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

Definition at line 165 of file context_vk_unittests.cc.

165 {
166 auto context =
167 MockVulkanContextBuilder()
168 .SetSettingsCallback(
169 [](auto& settings) { settings.enable_validation = true; })
170 .SetInstanceExtensions(
171 {"VK_KHR_surface", "VK_MVK_macos_surface", "VK_EXT_debug_utils"})
172 .SetInstanceLayers({"VK_LAYER_KHRONOS_validation"})
173 .Build();
174 ASSERT_NE(context, nullptr);
175 const CapabilitiesVK* capabilites_vk =
176 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
177 ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
178 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [38/389]

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() [39/389]

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

Definition at line 94 of file context_vk_unittests.cc.

94 {
95 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
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 PipelineFuture<PipelineDescriptor> pipeline_future =
102 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
103 pipeline = pipeline_future.Get();
104 ASSERT_TRUE(pipeline);
105 functions = GetMockVulkanFunctions(context->GetDevice());
106 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
107 "vkCreateGraphicsPipelines") != functions->end());
108 }
109 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
110 "vkDestroyDevice") != functions->end());
111 }

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

## ◆ TEST() [40/389]

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

Definition at line 135 of file context_vk_unittests.cc.

135 {
136 std::shared_ptr<PipelineLibrary> pipeline_library;
137 std::shared_ptr<std::vector<std::string>> functions;
138 {
139 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
140 PipelineDescriptor pipeline_desc;
141 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
142 pipeline_library = context->GetPipelineLibrary();
143 functions = GetMockVulkanFunctions(context->GetDevice());
144 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
145 "vkCreatePipelineCache") != functions->end());
146 }
147 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
148 "vkDestroyDevice") != functions->end());
149 }

References impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [41/389]

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() [42/389]

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() [43/389]

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

Definition at line 113 of file context_vk_unittests.cc.

113 {
114 std::shared_ptr<const ShaderFunction> shader_function;
115 std::shared_ptr<std::vector<std::string>> functions;
116 {
117 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
118 PipelineDescriptor pipeline_desc;
119 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
120 std::vector<uint8_t> data = {0x03, 0x02, 0x23, 0x07};
121 context->GetShaderLibrary()->RegisterFunction(
122 "foobar_fragment_main", ShaderStage::kFragment,
123 std::make_shared<fml::DataMapping>(data), [](bool) {});
124 shader_function = context->GetShaderLibrary()->GetFunction(
125 "foobar_fragment_main", ShaderStage::kFragment);
126 ASSERT_TRUE(shader_function);
127 functions = GetMockVulkanFunctions(context->GetDevice());
128 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
129 "vkCreateShaderModule") != functions->end());
130 }
131 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
132 "vkDestroyDevice") != functions->end());
133 }

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

## ◆ TEST() [44/389]

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

Definition at line 244 of file context_vk_unittests.cc.

244 {
245 EXPECT_DEATH(const std::shared_ptr<ContextVK> context =
246 MockVulkanContextBuilder()
247 .SetSettingsCallback([](ContextVK::Settings& settings) {
248 settings.enable_validation = true;
249 settings.fatal_missing_validations = true;
250 })
251 .Build(),
252 "");
253 }

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

## ◆ TEST() [45/389]

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

Definition at line 255 of file context_vk_unittests.cc.

255 {
256 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
257
258 const CapabilitiesVK* capabilites_vk =
259 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
260 ASSERT_NE(capabilites_vk->GetDefaultColorFormat(), PixelFormat::kUnknown);
261 }

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

## ◆ TEST() [46/389]

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

Definition at line 75 of file context_vk_unittests.cc.

75 {
76 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
77
78 fml::AutoResetWaitableEvent latch1, latch2;
79 std::weak_ptr<CommandPoolVK> weak_pool;
80 std::thread thread([&]() {
81 weak_pool = context->GetCommandPoolRecycler()->Get();
82 context->DisposeThreadLocalCachedResources();
83 latch1.Signal();
84 latch2.Wait();
85 });
86
87 latch1.Wait();
88 ASSERT_FALSE(weak_pool.lock());
89
90 latch2.Signal();
91 thread.join();
92 }

## ◆ TEST() [47/389]

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

Definition at line 233 of file context_vk_unittests.cc.

233 {
234 const std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
235
236 context->SetOffscreenFormat(PixelFormat::kR8G8B8A8UNormInt);
237 context->InitializeCommonlyUsedShadersIfNeeded();
238
239 auto functions = GetMockVulkanFunctions(context->GetDevice());
240 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
241 "vkCreateRenderPass") != functions->end());
242 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST() [48/389]

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() [49/389]

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() [50/389]

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() [51/389]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsRespectsSkipCounts |
| ) |  |

Definition at line 89 of file draw_order_resolver_unittests.cc.

89 {
90 DrawOrderResolver resolver;
91
92 // These items will be skipped.
93 resolver.AddElement(0, false);
94 resolver.AddElement(1, true);
95 resolver.AddElement(2, false);
96 // These ones will be included in the final draw list.
97 resolver.AddElement(3, false);
98 resolver.AddElement(4, true);
99 resolver.AddElement(5, true);
100
101 // Form the draw list, skipping elements 0, 1, and 2.
102 // This emulates what happens when entitypass applies the clear color
103 // optimization.
104 auto sorted_elements = resolver.GetSortedDraws(1, 2);
105
106 EXPECT_EQ(sorted_elements.size(), 3u);
107 // First, opaque items are drawn in reverse order.
108 EXPECT_EQ(sorted_elements[0], 5u);
109 EXPECT_EQ(sorted_elements[1], 4u);
110 // Then, translucent items are drawn.
111 EXPECT_EQ(sorted_elements[2], 3u);
112 }

References impeller::DrawOrderResolver::AddElement(), and impeller::DrawOrderResolver::GetSortedDraws().

## ◆ TEST() [52/389]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsReturnsCorrectOrderWithClips |
| ) |  |

Definition at line 33 of file draw_order_resolver_unittests.cc.

33 {
34 DrawOrderResolver resolver;
35
36 // Items before clip.
37 resolver.AddElement(0, false);
38 resolver.AddElement(1, true);
39 resolver.AddElement(2, false);
40 resolver.AddElement(3, true);
41
42 // Clip.
43 resolver.PushClip(4);
44 {
45 // Clipped items.
46 resolver.AddElement(5, false);
47 resolver.AddElement(6, false);
48 // Clipped translucent items.
49 resolver.AddElement(7, true);
50 resolver.AddElement(8, true);
51 }
52 resolver.PopClip();
53
54 // Items after clip.
55 resolver.AddElement(9, true);
56 resolver.AddElement(10, false);
57 resolver.AddElement(11, true);
58 resolver.AddElement(12, false);
59
60 auto sorted_elements = resolver.GetSortedDraws(0, 0);
61
62 EXPECT_EQ(sorted_elements.size(), 13u);
63 // First, all the non-clipped opaque items are drawn in reverse order.
64 EXPECT_EQ(sorted_elements[0], 11u);
65 EXPECT_EQ(sorted_elements[1], 9u);
66 EXPECT_EQ(sorted_elements[2], 3u);
67 EXPECT_EQ(sorted_elements[3], 1u);
68 // Then, non-clipped translucent items that came before the clip are drawn in
69 // their original order.
70 EXPECT_EQ(sorted_elements[4], 0u);
71 EXPECT_EQ(sorted_elements[5], 2u);
72
73 // Then, the clip and its sorted child items are drawn.
74 EXPECT_EQ(sorted_elements[6], 4u);
75 {
76 // Opaque clipped items are drawn in reverse order.
77 EXPECT_EQ(sorted_elements[7], 8u);
78 EXPECT_EQ(sorted_elements[8], 7u);
79 // Translucent clipped items are drawn.
80 EXPECT_EQ(sorted_elements[9], 5u);
81 EXPECT_EQ(sorted_elements[10], 6u);
82 }
83 // Finally, the non-clipped translucent items which came after the clip are
84 // drawn in their original order.
85 EXPECT_EQ(sorted_elements[11], 10u);
86 EXPECT_EQ(sorted_elements[12], 12u);
87 }

References impeller::DrawOrderResolver::AddElement(), impeller::DrawOrderResolver::GetSortedDraws(), impeller::DrawOrderResolver::PopClip(), and impeller::DrawOrderResolver::PushClip().

## ◆ TEST() [53/389]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsReturnsCorrectOrderWithFlush |
| ) |  |

Definition at line 114 of file draw_order_resolver_unittests.cc.

114 {
115 DrawOrderResolver resolver;
116
117 resolver.AddElement(0, false);
118 resolver.AddElement(1, true);
119 resolver.AddElement(2, false);
120 resolver.AddElement(3, true);
121
122 resolver.Flush();
123
124 resolver.AddElement(4, false);
125 resolver.AddElement(5, true);
126 resolver.AddElement(6, false);
127 resolver.AddElement(7, true);
128
129 resolver.Flush();
130
131 resolver.AddElement(8, false);
132 resolver.AddElement(9, true);
133 resolver.AddElement(10, false);
134 resolver.AddElement(11, true);
135
136 auto sorted_elements = resolver.GetSortedDraws(1, 1);
137
138 EXPECT_EQ(sorted_elements.size(), 10u);
139
140 // Skipped draws apply to the first flush.
141 EXPECT_EQ(sorted_elements[0], 3u);
142 EXPECT_EQ(sorted_elements[1], 2u);
143
144 EXPECT_EQ(sorted_elements[2], 7u);
145 EXPECT_EQ(sorted_elements[3], 5u);
146 EXPECT_EQ(sorted_elements[4], 4u);
147 EXPECT_EQ(sorted_elements[5], 6u);
148
149 EXPECT_EQ(sorted_elements[6], 11u);
150 EXPECT_EQ(sorted_elements[7], 9u);
151 EXPECT_EQ(sorted_elements[8], 8u);
152 EXPECT_EQ(sorted_elements[9], 10u);
153 }

References impeller::DrawOrderResolver::AddElement(), impeller::DrawOrderResolver::Flush(), and impeller::DrawOrderResolver::GetSortedDraws().

## ◆ TEST() [54/389]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsReturnsCorrectOrderWithNoClips |
| ) |  |

Definition at line 12 of file draw_order_resolver_unittests.cc.

12 {
13 DrawOrderResolver resolver;
14
15 // Opaque items.
16 resolver.AddElement(0, true);
17 resolver.AddElement(1, true);
18 // Translucent items.
19 resolver.AddElement(2, false);
20 resolver.AddElement(3, false);
21
22 auto sorted_elements = resolver.GetSortedDraws(0, 0);
23
24 EXPECT_EQ(sorted_elements.size(), 4u);
25 // First, the opaque items are drawn in reverse order.
26 EXPECT_EQ(sorted_elements[0], 1u);
27 EXPECT_EQ(sorted_elements[1], 0u);
28 // Then the translucent items are drawn.
29 EXPECT_EQ(sorted_elements[2], 2u);
30 EXPECT_EQ(sorted_elements[3], 3u);
31 }

References impeller::DrawOrderResolver::AddElement(), and impeller::DrawOrderResolver::GetSortedDraws().

## ◆ TEST() [55/389]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | CanIdentifyBadMaleoonDriver |
| ) |  |

Definition at line 39 of file driver_info_vk_unittests.cc.

39 {
40 auto const context =
41 MockVulkanContextBuilder()
42 .SetPhysicalPropertiesCallback(
43 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
44 prop->vendorID = 0x19E5; // Huawei
45 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
46 })
47 .Build();
48
49 EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver());
50 }

## ◆ TEST() [56/389]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | DisabledDevices |
| ) |  |

Definition at line 81 of file driver_info_vk_unittests.cc.

81 {
82 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 630"));
83 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 620"));
84 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 610"));
85 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 530"));
86 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 512"));
87 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 509"));
88 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 508"));
89 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 506"));
90 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 505"));
91 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 504"));
92 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 640"));
93
94 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 650"));
95 }

References IsBadVersionTest().

## ◆ TEST() [57/389]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | DriverParsingArm |
| ) |  |

Definition at line 76 of file driver_info_vk_unittests.cc.

76 {
77 EXPECT_EQ(GetAdrenoVersion("Adreno (TM) 540"), AdrenoGPU::kAdreno540);
78 EXPECT_EQ(GetAdrenoVersion("Foo Bar"), AdrenoGPU::kUnknown);
79 }

References impeller::GetAdrenoVersion(), impeller::kAdreno540, and impeller::kUnknown.

## ◆ TEST() [58/389]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | DriverParsingMali |
| ) |  |

Definition at line 70 of file driver_info_vk_unittests.cc.

70 {
71 EXPECT_EQ(GetMaliVersion("Mali-G51-MORE STUFF"), MaliGPU::kG51);
72 EXPECT_EQ(GetMaliVersion("Mali-G51"), MaliGPU::kG51);
73 EXPECT_EQ(GetMaliVersion("Mali-111111"), MaliGPU::kUnknown);
74 }

References impeller::GetMaliVersion(), impeller::kG51, and impeller::kUnknown.

## ◆ TEST() [59/389]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | EnabledDevicesAdreno |
| ) |  |

Definition at line 102 of file driver_info_vk_unittests.cc.

102 {
103 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 750"));
104 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 740"));
105 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 732"));
106 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 730"));
107 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 725"));
108 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 720"));
109 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 710"));
110 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 702"));
111 }

References IsBadVersionTest().

## ◆ TEST() [60/389]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | EnabledDevicesMali |
| ) |  |

Definition at line 97 of file driver_info_vk_unittests.cc.

97 {
98 EXPECT_FALSE(IsBadVersionTest("Mali-G52", /*qc=*/false));
99 EXPECT_FALSE(IsBadVersionTest("Mali-G54-MORE STUFF", /*qc=*/false));
100 }

References IsBadVersionTest().

## ◆ TEST() [61/389]

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

Definition at line 139 of file geometry_unittests.cc.

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

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

## ◆ TEST() [62/389]

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() [63/389]

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() [64/389]

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() [65/389]

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() [66/389]

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() [67/389]

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() [68/389]

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() [69/389]

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() [70/389]

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

Definition at line 197 of file entity_pass_unittests.cc.

197 {
198 EntityPassClipStack recorder =
199 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
200
201 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
202
203 // Push Clips that shrink in size. All should be applied.
204 Entity entity;
205
206 for (auto i = 1; i < 20; i++) {
207 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
208 Contents::ClipCoverage{
209 .type = Contents::ClipCoverage::Type::kAppend,
210 .coverage = Rect::MakeLTRB(i, i, 100 - i, 100 - i),
211 },
212 entity, 0, Point(0, 0));
213 EXPECT_TRUE(result.should_render);
214 EXPECT_TRUE(result.clip_did_change);
215 EXPECT_EQ(recorder.CurrentClipCoverage(),
216 Rect::MakeLTRB(i, i, 100 - i, 100 - i));
217 }
218 }

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

## ◆ TEST() [71/389]

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

Definition at line 220 of file entity_pass_unittests.cc.

220 {
221 EntityPassClipStack recorder =
222 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
223
224 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
225
226 // Push Clips that grow in size. All should be skipped.
227 Entity entity;
228
229 for (auto i = 1; i < 20; i++) {
230 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
231 Contents::ClipCoverage{
232 .type = Contents::ClipCoverage::Type::kAppend,
233 .coverage = Rect::MakeLTRB(0 - i, 0 - i, 100 + i, 100 + i),
234 },
235 entity, 0, Point(0, 0));
236 EXPECT_FALSE(result.should_render);
237 EXPECT_FALSE(result.clip_did_change);
238 EXPECT_EQ(recorder.CurrentClipCoverage(), Rect::MakeLTRB(0, 0, 100, 100));
239 }
240 }

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

## ◆ TEST() [72/389]

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

Definition at line 135 of file entity_pass_unittests.cc.

135 {
136 EntityPassClipStack recorder =
137 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
138
139 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
140
141 // Push a clip.
142 Entity entity;
143 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
144 Contents::ClipCoverage{
145 .type = Contents::ClipCoverage::Type::kAppend,
146 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
147 },
148 entity, 0, Point(0, 0));
149 EXPECT_TRUE(result.should_render);
150 EXPECT_TRUE(result.clip_did_change);
151
152 // Push a clip with larger coverage than the previous state.
153 result = recorder.ApplyClipState(
154 Contents::ClipCoverage{
155 .type = Contents::ClipCoverage::Type::kAppend,
156 .coverage = Rect::MakeLTRB(0, 0, 100, 100),
157 },
158 entity, 0, Point(0, 0));
159
160 EXPECT_FALSE(result.should_render);
161 EXPECT_FALSE(result.clip_did_change);
162 }

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

## ◆ TEST() [73/389]

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

Definition at line 166 of file entity_pass_unittests.cc.

167 {
168 EntityPassClipStack recorder =
169 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
170
171 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
172
173 // Push a clip.
174 Entity entity;
175 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
176 Contents::ClipCoverage{
177 .type = Contents::ClipCoverage::Type::kAppend,
178 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
179 },
180 entity, 0, Point(0, 0));
181 EXPECT_TRUE(result.should_render);
182 EXPECT_TRUE(result.clip_did_change);
183
184 // Push a clip with larger coverage than the previous state.
185 result = recorder.ApplyClipState(
186 Contents::ClipCoverage{
187 .type = Contents::ClipCoverage::Type::kAppend,
188 .is_difference_or_non_square = true,
189 .coverage = Rect::MakeLTRB(0, 0, 100, 100),
190 },
191 entity, 0, Point(0, 0));
192
193 EXPECT_TRUE(result.should_render);
194 EXPECT_TRUE(result.clip_did_change);
195 }

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

## ◆ TEST() [74/389]

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() [75/389]

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() [76/389]

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() [77/389]

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

Definition at line 269 of file entity_pass_unittests.cc.

269 {
270 EntityPassClipStack recorder =
271 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
272
273 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
274
275 // Push a clip.
276 Entity entity;
277 {
278 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
279 Contents::ClipCoverage{
280 .type = Contents::ClipCoverage::Type::kAppend,
281 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
282 },
283 entity, 0, Point(0, 0));
284 EXPECT_TRUE(result.should_render);
285 EXPECT_TRUE(result.clip_did_change);
286 }
287
288 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
289 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
290 Rect::MakeLTRB(50, 50, 55, 55));
291 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
292 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
293
294 // Begin a subpass.
295 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
296 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
297 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
298 Rect::MakeLTRB(50, 50, 55, 55));
299
300 {
301 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
302 Contents::ClipCoverage{
303 .type = Contents::ClipCoverage::Type::kAppend,
304 .coverage = Rect::MakeLTRB(54, 54, 55, 55),
305 },
306 entity, 0, Point(0, 0));
307 EXPECT_TRUE(result.should_render);
308 EXPECT_TRUE(result.clip_did_change);
309 }
310
311 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
312 Rect::MakeLTRB(54, 54, 55, 55));
313
314 // End subpass.
315 recorder.PopSubpass();
316
317 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
318 Rect::MakeLTRB(50, 50, 55, 55));
319 }

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() [78/389]

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

Definition at line 242 of file entity_pass_unittests.cc.

242 {
243 EntityPassClipStack recorder =
244 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
245
246 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
247
248 // Restore the clip.
249 Entity entity;
250 auto restore_clip = std::make_shared<ClipRestoreContents>();
251 restore_clip->SetRestoreHeight(0);
252 entity.SetContents(std::move(restore_clip));
253 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
254 Contents::ClipCoverage{
255 .type = Contents::ClipCoverage::Type::kRestore,
256 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
257 },
258 entity, 0, Point(0, 0));
259 EXPECT_FALSE(result.should_render);
260 EXPECT_FALSE(result.clip_did_change);
261
262 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
263 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
264 Rect::MakeSize(Size::MakeWH(100, 100)));
265 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
266 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
267 }

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() [79/389]

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() [80/389]

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() [81/389]

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() [82/389]

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() [83/389]

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

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

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

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

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

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

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

Definition at line 458 of file gaussian_blur_filter_contents_unittests.cc.

458 {
459 Scalar sigma = 1.0;
460 Scalar radius = GaussianBlurFilterContents::CalculateBlurRadius(
461 GaussianBlurFilterContents::ScaleSigma(sigma));
462 fml::StatusOr<Scalar> derived_sigma =
463 CalculateSigmaForBlurRadius(radius, Matrix());
464 ASSERT_TRUE(derived_sigma.ok());
465 EXPECT_NEAR(sigma, derived_sigma.value(), 0.01f);
466 }

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

## ◆ TEST() [90/389]

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

Definition at line 225 of file gaussian_blur_filter_contents_unittests.cc.

225 {
226 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
227 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
228 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
229 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
230 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
231 // Hang on to 1/8 as long as possible.
232 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(95.0f), 0.125);
233 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(96.0f), 0.0625);
234 // Downsample clamped to 1/16th.
235 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 0.0625);
236 }

References impeller::GaussianBlurFilterContents::CalculateScale().

## ◆ TEST() [91/389]

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

Definition at line 621 of file gaussian_blur_filter_contents_unittests.cc.

621 {
622 Scalar sigma = 30.5f;
623 int32_t blur_radius = static_cast<int32_t>(
624 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
625 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
626 .blur_sigma = sigma,
627 .blur_radius = blur_radius,
628 .step_size = 1};
629 KernelSamples kernel_samples = GenerateBlurInfo(parameters);
630 GaussianBlurPipeline::FragmentShader::KernelSamples frag_kernel_samples =
631 LerpHackKernelSamples(kernel_samples);
632 EXPECT_TRUE(frag_kernel_samples.sample_count <= kGaussianBlurMaxKernelSize);
633 }

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

## ◆ TEST() [92/389]

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

Definition at line 468 of file gaussian_blur_filter_contents_unittests.cc.

468 {
469 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
470 .blur_sigma = 1,
471 .blur_radius = 5,
472 .step_size = 1};
473 KernelSamples samples = GenerateBlurInfo(parameters);
474 EXPECT_EQ(samples.sample_count, 9);
475
476 // Coefficients should add up to 1.
477 Scalar tally = 0;
478 for (int i = 0; i < samples.sample_count; ++i) {
479 tally += samples.samples[i].coefficient;
480 }
481 EXPECT_FLOAT_EQ(tally, 1.0f);
482
483 // Verify the shape of the curve.
484 for (int i = 0; i < 4; ++i) {
485 EXPECT_FLOAT_EQ(samples.samples[i].coefficient,
486 samples.samples[8 - i].coefficient);
487 EXPECT_TRUE(samples.samples[i + 1].coefficient >
488 samples.samples[i].coefficient);
489 }
490 }

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

## ◆ TEST() [93/389]

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

Definition at line 121 of file gaussian_blur_filter_contents_unittests.cc.

121 {
122 GaussianBlurFilterContents contents(
123 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
124 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
125 FilterInput::Vector inputs = {};
126 Entity entity;
127 std::optional<Rect> coverage =
128 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
129 ASSERT_FALSE(coverage.has_value());
130 }

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

## ◆ TEST() [94/389]

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

Definition at line 132 of file gaussian_blur_filter_contents_unittests.cc.

132 {
133 GaussianBlurFilterContents contents(
134 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
135 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
136 FilterInput::Vector inputs = {
137 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
138 Entity entity;
139 std::optional<Rect> coverage =
140 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
141
142 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
143 }

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

## ◆ TEST() [95/389]

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

Definition at line 145 of file gaussian_blur_filter_contents_unittests.cc.

145 {
146 fml::StatusOr<Scalar> sigma_radius_1 =
147 CalculateSigmaForBlurRadius(1.0, Matrix());
148 ASSERT_TRUE(sigma_radius_1.ok());
149 GaussianBlurFilterContents contents(
150 /*sigma_x=*/sigma_radius_1.value(),
151 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
152 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
153 FilterInput::Vector inputs = {
154 FilterInput::Make(Rect::MakeLTRB(100, 100, 200, 200))};
155 Entity entity;
156 std::optional<Rect> coverage =
157 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
158
159 EXPECT_TRUE(coverage.has_value());
160 if (coverage.has_value()) {
161 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
162 }
163 }

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

## ◆ TEST() [96/389]

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

Definition at line 113 of file gaussian_blur_filter_contents_unittests.cc.

113 {
114 GaussianBlurFilterContents contents(
115 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
116 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
117 EXPECT_EQ(contents.GetSigmaX(), 0.0);
118 EXPECT_EQ(contents.GetSigmaY(), 0.0);
119 }

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

## ◆ TEST() [97/389]

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

Definition at line 208 of file gaussian_blur_filter_contents_unittests.cc.

208 {
209 fml::StatusOr<Scalar> sigma_radius_1 =
210 CalculateSigmaForBlurRadius(1.0, Matrix());
211 ASSERT_TRUE(sigma_radius_1.ok());
212 auto contents = std::make_unique<GaussianBlurFilterContents>(
213 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
214 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
215 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
216 /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
217 /*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
218 EXPECT_TRUE(coverage.has_value());
219 if (coverage.has_value()) {
220 EXPECT_RECT_NEAR(coverage.value(),
221 Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
222 }
223 }

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

## ◆ TEST() [98/389]

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

Definition at line 567 of file gaussian_blur_filter_contents_unittests.cc.

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

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

## ◆ TEST() [99/389]

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

Definition at line 492 of file gaussian_blur_filter_contents_unittests.cc.

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

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

## ◆ TEST() [100/389]

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

Definition at line 1663 of file geometry_unittests.cc.

1663 {
1664 using BlendT = std::underlying_type_t<BlendMode>;
1665 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLast); i++) {
1666 auto mode = static_cast<BlendMode>(i);
1667 auto result = BlendModeToString(mode);
1668 switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) }
1669 }
1670 }

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

## ◆ TEST() [101/389]

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

Definition at line 1672 of file geometry_unittests.cc.

1672 {
1673 {
1674 auto deg = Degrees{90.0};
1675 Radians rad = deg;
1676 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1677 }
1678 }

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

## ◆ TEST() [102/389]

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

Definition at line 593 of file geometry_unittests.cc.

593 {
594 {
595 Point p1(1.0, 2.0);
596 IPoint p2 = static_cast<IPoint>(p1);
597 ASSERT_EQ(p2.x, 1u);
598 ASSERT_EQ(p2.y, 2u);
599 }
600
601 {
602 Size s1(1.0, 2.0);
603 ISize s2 = static_cast<ISize>(s1);
604 ASSERT_EQ(s2.width, 1u);
605 ASSERT_EQ(s2.height, 2u);
606 }
607
608 {
609 Size s1(1.0, 2.0);
610 Point p1 = static_cast<Point>(s1);
611 ASSERT_EQ(p1.x, 1u);
612 ASSERT_EQ(p1.y, 2u);
613 }
614 }

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

## ◆ TEST() [103/389]

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

Definition at line 580 of file geometry_unittests.cc.

580 {
581 ASSERT_EQ((Size{128, 128}.MipCount()), 7u);
582 ASSERT_EQ((Size{128, 256}.MipCount()), 8u);
583 ASSERT_EQ((Size{128, 130}.MipCount()), 8u);
584 ASSERT_EQ((Size{128, 257}.MipCount()), 9u);
585 ASSERT_EQ((Size{257, 128}.MipCount()), 9u);
586 ASSERT_EQ((Size{128, 0}.MipCount()), 1u);
587 ASSERT_EQ((Size{128, -25}.MipCount()), 1u);
588 ASSERT_EQ((Size{-128, 25}.MipCount()), 1u);
589 ASSERT_EQ((Size{1, 1}.MipCount()), 1u);
590 ASSERT_EQ((Size{0, 0}.MipCount()), 1u);
591 }

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

## ◆ TEST() [104/389]

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

Definition at line 616 of file geometry_unittests.cc.

616 {
617 {
618 IPoint p1(1, 2);
619 IPoint p2 = p1 + IPoint(1, 2);
620 ASSERT_EQ(p2.x, 2u);
621 ASSERT_EQ(p2.y, 4u);
622 }
623
624 {
625 IPoint p1(3, 6);
626 IPoint p2 = p1 - IPoint(1, 2);
627 ASSERT_EQ(p2.x, 2u);
628 ASSERT_EQ(p2.y, 4u);
629 }
630
631 {
632 IPoint p1(1, 2);
633 IPoint p2 = p1 * IPoint(2, 3);
634 ASSERT_EQ(p2.x, 2u);
635 ASSERT_EQ(p2.y, 6u);
636 }
637
638 {
639 IPoint p1(2, 6);
640 IPoint p2 = p1 / IPoint(2, 3);
641 ASSERT_EQ(p2.x, 1u);
642 ASSERT_EQ(p2.y, 2u);
643 }
644 }

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

## ◆ TEST() [105/389]

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

Definition at line 646 of file geometry_unittests.cc.

646 {
647 // LHS
648 {
649 IPoint p1(1, 2);
650 IPoint p2 = p1 * 2.0f;
651 ASSERT_EQ(p2.x, 2u);
652 ASSERT_EQ(p2.y, 4u);
653 }
654
655 {
656 IPoint p1(2, 6);
657 IPoint p2 = p1 / 2.0f;
658 ASSERT_EQ(p2.x, 1u);
659 ASSERT_EQ(p2.y, 3u);
660 }
661
662 // RHS
663 {
664 IPoint p1(1, 2);
665 IPoint p2 = 2.0f * p1;
666 ASSERT_EQ(p2.x, 2u);
667 ASSERT_EQ(p2.y, 4u);
668 }
669
670 {
671 IPoint p1(2, 6);
672 IPoint p2 = 12.0f / p1;
673 ASSERT_EQ(p2.x, 6u);
674 ASSERT_EQ(p2.y, 2u);
675 }
676 }

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

## ◆ TEST() [106/389]

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

Definition at line 1230 of file geometry_unittests.cc.

1230 {
1231 {
1232 Vector3 p1(1, 2, 3);
1233 Vector3 p2 = p1 + Vector3(1, 2, 3);
1234 ASSERT_EQ(p2.x, 2u);
1235 ASSERT_EQ(p2.y, 4u);
1236 ASSERT_EQ(p2.z, 6u);
1237 }
1238
1239 {
1240 Vector3 p1(3, 6, 9);
1241 Vector3 p2 = p1 - Vector3(1, 2, 3);
1242 ASSERT_EQ(p2.x, 2u);
1243 ASSERT_EQ(p2.y, 4u);
1244 ASSERT_EQ(p2.z, 6u);
1245 }
1246
1247 {
1248 Vector3 p1(1, 2, 3);
1249 Vector3 p2 = p1 * Vector3(2, 3, 4);
1250 ASSERT_EQ(p2.x, 2u);
1251 ASSERT_EQ(p2.y, 6u);
1252 ASSERT_EQ(p2.z, 12u);
1253 }
1254
1255 {
1256 Vector3 p1(2, 6, 12);
1257 Vector3 p2 = p1 / Vector3(2, 3, 4);
1258 ASSERT_EQ(p2.x, 1u);
1259 ASSERT_EQ(p2.y, 2u);
1260 ASSERT_EQ(p2.z, 3u);
1261 }
1262 }

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

## ◆ TEST() [107/389]

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

Definition at line 1264 of file geometry_unittests.cc.

1264 {
1265 // LHS
1266 {
1267 Vector3 p1(1, 2, 3);
1268 Vector3 p2 = p1 + 2.0f;
1269 ASSERT_EQ(p2.x, 3);
1270 ASSERT_EQ(p2.y, 4);
1271 ASSERT_EQ(p2.z, 5);
1272 }
1273
1274 {
1275 Vector3 p1(1, 2, 3);
1276 Vector3 p2 = p1 - 2.0f;
1277 ASSERT_EQ(p2.x, -1);
1278 ASSERT_EQ(p2.y, 0);
1279 ASSERT_EQ(p2.z, 1);
1280 }
1281
1282 {
1283 Vector3 p1(1, 2, 3);
1284 Vector3 p2 = p1 * 2.0f;
1285 ASSERT_EQ(p2.x, 2);
1286 ASSERT_EQ(p2.y, 4);
1287 ASSERT_EQ(p2.z, 6);
1288 }
1289
1290 {
1291 Vector3 p1(2, 6, 12);
1292 Vector3 p2 = p1 / 2.0f;
1293 ASSERT_EQ(p2.x, 1);
1294 ASSERT_EQ(p2.y, 3);
1295 ASSERT_EQ(p2.z, 6);
1296 }
1297
1298 // RHS
1299 {
1300 Vector3 p1(1, 2, 3);
1301 Vector3 p2 = 2.0f + p1;
1302 ASSERT_EQ(p2.x, 3);
1303 ASSERT_EQ(p2.y, 4);
1304 ASSERT_EQ(p2.z, 5);
1305 }
1306
1307 {
1308 Vector3 p1(1, 2, 3);
1309 Vector3 p2 = 2.0f - p1;
1310 ASSERT_EQ(p2.x, 1);
1311 ASSERT_EQ(p2.y, 0);
1312 ASSERT_EQ(p2.z, -1);
1313 }
1314
1315 {
1316 Vector3 p1(1, 2, 3);
1317 Vector3 p2 = 2.0f * p1;
1318 ASSERT_EQ(p2.x, 2);
1319 ASSERT_EQ(p2.y, 4);
1320 ASSERT_EQ(p2.z, 6);
1321 }
1322
1323 {
1324 Vector3 p1(2, 6, 12);
1325 Vector3 p2 = 12.0f / p1;
1326 ASSERT_EQ(p2.x, 6);
1327 ASSERT_EQ(p2.y, 2);
1328 ASSERT_EQ(p2.z, 1);
1329 }
1330 }

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

## ◆ TEST() [108/389]

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

Definition at line 798 of file geometry_unittests.cc.

798 {
799 // Point on RHS
800 {
801 IPoint p(1, 2);
802 p += IPoint(1, 2);
803 ASSERT_EQ(p.x, 2u);
804 ASSERT_EQ(p.y, 4u);
805 }
806
807 {
808 IPoint p(3, 6);
809 p -= IPoint(1, 2);
810 ASSERT_EQ(p.x, 2u);
811 ASSERT_EQ(p.y, 4u);
812 }
813
814 {
815 IPoint p(1, 2);
816 p *= IPoint(2, 3);
817 ASSERT_EQ(p.x, 2u);
818 ASSERT_EQ(p.y, 6u);
819 }
820
821 {
822 IPoint p(2, 6);
823 p /= IPoint(2, 3);
824 ASSERT_EQ(p.x, 1u);
825 ASSERT_EQ(p.y, 2u);
826 }
827
828 // Size on RHS
829 {
830 IPoint p(1, 2);
831 p += ISize(1, 2);
832 ASSERT_EQ(p.x, 2u);
833 ASSERT_EQ(p.y, 4u);
834 }
835
836 {
837 IPoint p(3, 6);
838 p -= ISize(1, 2);
839 ASSERT_EQ(p.x, 2u);
840 ASSERT_EQ(p.y, 4u);
841 }
842
843 {
844 IPoint p(1, 2);
845 p *= ISize(2, 3);
846 ASSERT_EQ(p.x, 2u);
847 ASSERT_EQ(p.y, 6u);
848 }
849
850 {
851 IPoint p(2, 6);
852 p /= ISize(2, 3);
853 ASSERT_EQ(p.x, 1u);
854 ASSERT_EQ(p.y, 2u);
855 }
856
857 // Arithmetic type on RHS
858 {
859 IPoint p(1, 2);
860 p *= 3;
861 ASSERT_EQ(p.x, 3u);
862 ASSERT_EQ(p.y, 6u);
863 }
864
865 {
866 IPoint p(3, 6);
867 p /= 3;
868 ASSERT_EQ(p.x, 1u);
869 ASSERT_EQ(p.y, 2u);
870 }
871 }

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

## ◆ TEST() [109/389]

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

Definition at line 1180 of file geometry_unittests.cc.

1180 {
1181 {
1182 Vector3 p(1, 2, 4);
1183 p += Vector3(1, 2, 4);
1184 ASSERT_EQ(p.x, 2u);
1185 ASSERT_EQ(p.y, 4u);
1186 ASSERT_EQ(p.z, 8u);
1187 }
1188
1189 {
1190 Vector3 p(3, 6, 8);
1191 p -= Vector3(1, 2, 3);
1192 ASSERT_EQ(p.x, 2u);
1193 ASSERT_EQ(p.y, 4u);
1194 ASSERT_EQ(p.z, 5u);
1195 }
1196
1197 {
1198 Vector3 p(1, 2, 3);
1199 p *= Vector3(2, 3, 4);
1200 ASSERT_EQ(p.x, 2u);
1201 ASSERT_EQ(p.y, 6u);
1202 ASSERT_EQ(p.z, 12u);
1203 }
1204
1205 {
1206 Vector3 p(1, 2, 3);
1207 p *= 2;
1208 ASSERT_EQ(p.x, 2u);
1209 ASSERT_EQ(p.y, 4u);
1210 ASSERT_EQ(p.z, 6u);
1211 }
1212
1213 {
1214 Vector3 p(2, 6, 12);
1215 p /= Vector3(2, 3, 4);
1216 ASSERT_EQ(p.x, 1u);
1217 ASSERT_EQ(p.y, 2u);
1218 ASSERT_EQ(p.z, 3u);
1219 }
1220
1221 {
1222 Vector3 p(2, 6, 12);
1223 p /= 2;
1224 ASSERT_EQ(p.x, 1u);
1225 ASSERT_EQ(p.y, 3u);
1226 ASSERT_EQ(p.z, 6u);
1227 }
1228 }

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

## ◆ TEST() [110/389]

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

Definition at line 1437 of file geometry_unittests.cc.

1437 {
1438 {
1439 ColorMatrix color_matrix = {
1440 1, 1, 1, 1, 1, //
1441 1, 1, 1, 1, 1, //
1442 1, 1, 1, 1, 1, //
1443 1, 1, 1, 1, 1, //
1444 };
1445 auto result = Color::White().ApplyColorMatrix(color_matrix);
1446 auto expected = Color(1, 1, 1, 1);
1447 ASSERT_COLOR_NEAR(result, expected);
1448 }
1449
1450 {
1451 ColorMatrix color_matrix = {
1452 0.1, 0, 0, 0, 0.01, //
1453 0, 0.2, 0, 0, 0.02, //
1454 0, 0, 0.3, 0, 0.03, //
1455 0, 0, 0, 0.4, 0.04, //
1456 };
1457 auto result = Color::White().ApplyColorMatrix(color_matrix);
1458 auto expected = Color(0.11, 0.22, 0.33, 0.44);
1459 ASSERT_COLOR_NEAR(result, expected);
1460 }
1461 }

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

## ◆ TEST() [111/389]

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

Definition at line 1646 of file geometry_unittests.cc.

1646 {
1647 Color dst = ColorBlendTestData::kDestinationColor;
1648 for (size_t source_i = 0;
1649 source_i < sizeof(ColorBlendTestData::kSourceColors) / sizeof(Color);
1650 source_i++) {
1651 Color src = ColorBlendTestData::kSourceColors[source_i];
1652
1653 Color expected;
1654 IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_RESULT_CHECK)
1655 }
1656 }

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

## ◆ TEST() [112/389]

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

Definition at line 1397 of file geometry_unittests.cc.

1397 {
1398 {
1399 Color result = Color(0.5, 0.5, 0.5, 0.5).Clamp01();
1400 Color expected = Color(0.5, 0.5, 0.5, 0.5);
1401 ASSERT_COLOR_NEAR(result, expected);
1402 }
1403
1404 {
1405 Color result = Color(-1, -1, -1, -1).Clamp01();
1406 Color expected = Color(0, 0, 0, 0);
1407 ASSERT_COLOR_NEAR(result, expected);
1408 }
1409
1410 {
1411 Color result = Color(2, 2, 2, 2).Clamp01();
1412 Color expected = Color(1, 1, 1, 1);
1413 ASSERT_COLOR_NEAR(result, expected);
1414 }
1415 }

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

## ◆ TEST() [113/389]

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

Definition at line 1375 of file geometry_unittests.cc.

1375 {
1376 {
1377 Color a(0.0, 0.0, 0.0, 0.0);
1378 Color b(1.0, 1.0, 1.0, 1.0);
1379
1380 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.5, 0.5, 0.5, 0.5));
1381 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1382 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1383 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.2, 0.2, 0.2, 0.2));
1384 }
1385
1386 {
1387 Color a(0.2, 0.4, 1.0, 0.5);
1388 Color b(0.4, 1.0, 0.2, 0.3);
1389
1390 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.3, 0.7, 0.6, 0.4));
1391 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1392 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1393 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.24, 0.52, 0.84, 0.46));
1394 }
1395 }

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

## ◆ TEST() [114/389]

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

Definition at line 1463 of file geometry_unittests.cc.

1463 {
1464 {
1465 auto result = Color::White().LinearToSRGB();
1466 auto expected = Color(1, 1, 1, 1);
1467 ASSERT_COLOR_NEAR(result, expected);
1468 }
1469
1470 {
1471 auto result = Color::BlackTransparent().LinearToSRGB();
1472 auto expected = Color(0, 0, 0, 0);
1473 ASSERT_COLOR_NEAR(result, expected);
1474 }
1475
1476 {
1477 auto result = Color(0.2, 0.4, 0.6, 0.8).LinearToSRGB();
1478 auto expected = Color(0.484529, 0.665185, 0.797738, 0.8);
1479 ASSERT_COLOR_NEAR(result, expected);
1480 }
1481 }

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

## ◆ TEST() [115/389]

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

Definition at line 1417 of file geometry_unittests.cc.

1417 {
1418 {
1419 Color a = Color::MakeRGBA8(0, 0, 0, 0);
1420 Color b = Color::BlackTransparent();
1421 ASSERT_COLOR_NEAR(a, b);
1422 }
1423
1424 {
1425 Color a = Color::MakeRGBA8(255, 255, 255, 255);
1426 Color b = Color::White();
1427 ASSERT_COLOR_NEAR(a, b);
1428 }
1429
1430 {
1431 Color a = Color::MakeRGBA8(63, 127, 191, 127);
1432 Color b(0.247059, 0.498039, 0.74902, 0.498039);
1433 ASSERT_COLOR_NEAR(a, b);
1434 }
1435 }

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

## ◆ TEST() [116/389]

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

Definition at line 1332 of file geometry_unittests.cc.

1332 {
1333 {
1334 Color a(1.0, 0.5, 0.2, 0.5);
1335 Color premultiplied = a.Premultiply();
1336 Color expected = Color(0.5, 0.25, 0.1, 0.5);
1337 ASSERT_COLOR_NEAR(premultiplied, expected);
1338 }
1339
1340 {
1341 Color a(0.5, 0.25, 0.1, 0.5);
1342 Color unpremultiplied = a.Unpremultiply();
1343 Color expected = Color(1.0, 0.5, 0.2, 0.5);
1344 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1345 }
1346
1347 {
1348 Color a(0.5, 0.25, 0.1, 0.0);
1349 Color unpremultiplied = a.Unpremultiply();
1350 Color expected = Color(0.0, 0.0, 0.0, 0.0);
1351 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1352 }
1353 }

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

## ◆ TEST() [117/389]

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

Definition at line 1755 of file geometry_unittests.cc.

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

## ◆ TEST() [118/389]

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

Definition at line 1355 of file geometry_unittests.cc.

1355 {
1356 {
1357 Color a(1.0, 0.5, 0.2, 0.5);
1358 std::array<uint8_t, 4> expected = {255, 128, 51, 128};
1359 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1360 }
1361
1362 {
1363 Color a(0.0, 0.0, 0.0, 0.0);
1364 std::array<uint8_t, 4> expected = {0, 0, 0, 0};
1365 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1366 }
1367
1368 {
1369 Color a(1.0, 1.0, 1.0, 1.0);
1370 std::array<uint8_t, 4> expected = {255, 255, 255, 255};
1371 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1372 }
1373 }

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

## ◆ TEST() [119/389]

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

Definition at line 1483 of file geometry_unittests.cc.

1483 {
1484 {
1485 auto result = Color::White().SRGBToLinear();
1486 auto expected = Color(1, 1, 1, 1);
1487 ASSERT_COLOR_NEAR(result, expected);
1488 }
1489
1490 {
1491 auto result = Color::BlackTransparent().SRGBToLinear();
1492 auto expected = Color(0, 0, 0, 0);
1493 ASSERT_COLOR_NEAR(result, expected);
1494 }
1495
1496 {
1497 auto result = Color(0.2, 0.4, 0.6, 0.8).SRGBToLinear();
1498 auto expected = Color(0.0331048, 0.132868, 0.318547, 0.8);
1499 ASSERT_COLOR_NEAR(result, expected);
1500 }
1501 }

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

## ◆ TEST() [120/389]

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() [121/389]

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

Definition at line 1777 of file geometry_unittests.cc.

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

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() [122/389]

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

Definition at line 1847 of file geometry_unittests.cc.

1847 {
1848 #if defined(FML_OS_MACOSX) || defined(FML_OS_IOS) || \
1849 defined(FML_OS_IOS_SIMULATOR)
1850 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
1851 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
1852 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
1853 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
1854
1855 // 65504 is the largest possible half.
1856 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
1857 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
1858
1859 // Colors
1860 ASSERT_EQ(HalfVector4(Color::Red()),
1861 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
1862 ASSERT_EQ(HalfVector4(Color::Green()),
1863 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
1864 ASSERT_EQ(HalfVector4(Color::Blue()),
1865 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
1866 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
1867 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
1868
1869 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
1870 HalfVector3(4.0f16, 6.0f16, -1.0f16));
1871 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
1872
1873 ASSERT_EQ(Half(0.5f), Half(0.5f16));
1874 ASSERT_EQ(Half(0.5), Half(0.5f16));
1875 ASSERT_EQ(Half(5), Half(5.0f16));
1876 #else
1877 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
1878 "only used on Apple platforms.";
1879 #endif // FML_OS_MACOSX || FML_OS_IOS || FML_OS_IOS_SIMULATOR
1880 }

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

## ◆ TEST() [123/389]

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() [124/389]

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() [125/389]

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

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() [127/389]

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() [128/389]

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

Definition at line 408 of file geometry_unittests.cc.

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

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

## ◆ TEST() [129/389]

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

Definition at line 432 of file geometry_unittests.cc.

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

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

## ◆ TEST() [130/389]

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

Definition at line 333 of file geometry_unittests.cc.

333 {
334 {
335 auto m = Matrix::MakeScale({3, 1, 1});
336 ASSERT_EQ(m.GetMaxBasisLengthXY(), 3);
337
338 m = m * Matrix::MakeSkew(0, 4);
339 ASSERT_EQ(m.GetMaxBasisLengthXY(), 5);
340 }
341
342 {
343 auto m = Matrix::MakeScale({-3, 4, 7});
344 ASSERT_EQ(m.GetMaxBasisLengthXY(), 4);
345 }
346
347 {
348 // clang-format off
349 auto m = Matrix::MakeColumn(
350 1.0f, 0.0f, 0.0f, 0.0f,
351 0.0f, 1.0f, 0.0f, 0.0f,
352 4.0f, 0.0f, 1.0f, 0.0f,
353 0.0f, 0.0f, 0.0f, 1.0f
354 );
355 // clang-format on
356 ASSERT_EQ(m.GetMaxBasisLengthXY(), 1.0f);
357 }
358 }

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

## ◆ TEST() [131/389]

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

Definition at line 481 of file geometry_unittests.cc.

481 {
482 {
483 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
484 Vector3(0, 1, 0));
485 auto expected = Matrix{
486 1, 0, 0, 0, //
487 0, 1, 0, 0, //
488 0, 0, 1, 0, //
489 0, 0, 1, 1, //
490 };
491 ASSERT_MATRIX_NEAR(m, expected);
492 }
493
494 // Sideways tilt.
495 {
496 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
497 Vector3(1, 1, 0).Normalize());
498
499 // clang-format off
500 auto expected = Matrix{
501 k1OverSqrt2, k1OverSqrt2, 0, 0,
502 -k1OverSqrt2, k1OverSqrt2, 0, 0,
503 0, 0, 1, 0,
504 0, 0, 1, 1,
505 };
506 // clang-format on
507 ASSERT_MATRIX_NEAR(m, expected);
508 }
509
510 // Half way between +x and -y, yaw 90
511 {
512 auto m =
513 Matrix::MakeLookAt(Vector3(), Vector3(10, -10, 0), Vector3(0, 0, -1));
514
515 // clang-format off
516 auto expected = Matrix{
517 -k1OverSqrt2, 0, k1OverSqrt2, 0,
518 -k1OverSqrt2, 0, -k1OverSqrt2, 0,
519 0, -1, 0, 0,
520 0, 0, 0, 1,
521 };
522 // clang-format on
523 ASSERT_MATRIX_NEAR(m, expected);
524 }
525 }

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

## ◆ TEST() [132/389]

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

Definition at line 360 of file geometry_unittests.cc.

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

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

## ◆ TEST() [133/389]

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

Definition at line 384 of file geometry_unittests.cc.

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

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

## ◆ TEST() [134/389]

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() [135/389]

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

Definition at line 1680 of file geometry_unittests.cc.

1680 {
1681 {
1682 std::stringstream stream;
1683 Matrix m;
1684 stream << m;
1685 ASSERT_EQ(stream.str(), R"((
1686 1.000000, 0.000000, 0.000000, 0.000000,
1687 0.000000, 1.000000, 0.000000, 0.000000,
1688 0.000000, 0.000000, 1.000000, 0.000000,
1689 0.000000, 0.000000, 0.000000, 1.000000,
1690 ))");
1691 }
1692
1693 {
1694 std::stringstream stream;
1695 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
1696 stream << m;
1697
1698 ASSERT_EQ(stream.str(), R"((
1699 1.000000, 0.000000, 0.000000, 10.000000,
1700 0.000000, 1.000000, 0.000000, 20.000000,
1701 0.000000, 0.000000, 1.000000, 30.000000,
1702 0.000000, 0.000000, 0.000000, 1.000000,
1703 ))");
1704 }
1705 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [136/389]

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() [137/389]

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

Definition at line 455 of file geometry_unittests.cc.

455 {
456 {
457 auto m = Matrix();
458 bool result = m.IsTranslationScaleOnly();
459 ASSERT_TRUE(result);
460 }
461
462 {
463 auto m = Matrix::MakeScale(Vector3(2, 3, 4));
464 bool result = m.IsTranslationScaleOnly();
465 ASSERT_TRUE(result);
466 }
467
468 {
469 auto m = Matrix::MakeTranslation(Vector3(2, 3, 4));
470 bool result = m.IsTranslationScaleOnly();
471 ASSERT_TRUE(result);
472 }
473
474 {
475 auto m = Matrix::MakeRotationZ(Degrees(10));
476 bool result = m.IsTranslationScaleOnly();
477 ASSERT_FALSE(result);
478 }
479 }

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

## ◆ TEST() [138/389]

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() [139/389]

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() [140/389]

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

Definition at line 938 of file geometry_unittests.cc.

938 {
939 Point a(-1, -2);
940 auto a_abs = a.Abs();
941 auto expected = Point(1, 2);
942 ASSERT_POINT_NEAR(a_abs, expected);
943 }

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

## ◆ TEST() [141/389]

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

Definition at line 975 of file geometry_unittests.cc.

975 {
976 // Negative result in the CCW (with up = -Y) direction.
977 {
978 Point a(1, 1);
979 Point b(1, -1);
980 Radians actual = a.AngleTo(b);
981 Radians expected = Radians{-kPi / 2};
982 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
983 }
984
985 // Check the other direction to ensure the result is signed correctly.
986 {
987 Point a(1, -1);
988 Point b(1, 1);
989 Radians actual = a.AngleTo(b);
990 Radians expected = Radians{kPi / 2};
991 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
992 }
993
994 // Differences in magnitude should have no impact on the result.
995 {
996 Point a(100, -100);
997 Point b(0.01, 0.01);
998 Radians actual = a.AngleTo(b);
999 Radians expected = Radians{kPi / 2};
1000 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
1001 }
1002 }

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

## ◆ TEST() [142/389]

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

Definition at line 1067 of file geometry_unittests.cc.

1067 {
1068 Point p(1.5, 2.3);
1069 Point result = p.Ceil();
1070 Point expected(2, 3);
1071 ASSERT_POINT_NEAR(result, expected);
1072 }

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

## ◆ TEST() [143/389]

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

Definition at line 893 of file geometry_unittests.cc.

893 {
894 {
895 Point p(1, 0);
896 Scalar s = p.Cross(Point(-1, 0));
897 ASSERT_FLOAT_EQ(s, 0);
898 }
899
900 {
901 Point p(0, -1);
902 Scalar s = p.Cross(Point(-1, 0));
903 ASSERT_FLOAT_EQ(s, -1);
904 }
905
906 {
907 Point p(1, 2);
908 Scalar s = p.Cross(Point(3, -4));
909 ASSERT_FLOAT_EQ(s, -10);
910 }
911 }

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

## ◆ TEST() [144/389]

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

Definition at line 873 of file geometry_unittests.cc.

873 {
874 {
875 Point p(1, 0);
876 Scalar s = p.Dot(Point(-1, 0));
877 ASSERT_FLOAT_EQ(s, -1);
878 }
879
880 {
881 Point p(0, -1);
882 Scalar s = p.Dot(Point(-1, 0));
883 ASSERT_FLOAT_EQ(s, 0);
884 }
885
886 {
887 Point p(1, 2);
888 Scalar s = p.Dot(Point(3, -4));
889 ASSERT_FLOAT_EQ(s, -5);
890 }
891 }

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

## ◆ TEST() [145/389]

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

Definition at line 1046 of file geometry_unittests.cc.

1046 {
1047 Point p(1.5, 2.3);
1048 Point result = p.Floor();
1049 Point expected(1, 2);
1050 ASSERT_POINT_NEAR(result, expected);
1051 }

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

## ◆ TEST() [146/389]

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

Definition at line 678 of file geometry_unittests.cc.

678 {
679 // Integer on LHS, float on RHS
680 {
681 IPoint p1(1, 2);
682 Point p2 = p1 + Point(1, 2);
683 ASSERT_FLOAT_EQ(p2.x, 2u);
684 ASSERT_FLOAT_EQ(p2.y, 4u);
685 }
686
687 {
688 IPoint p1(3, 6);
689 Point p2 = p1 - Point(1, 2);
690 ASSERT_FLOAT_EQ(p2.x, 2u);
691 ASSERT_FLOAT_EQ(p2.y, 4u);
692 }
693
694 {
695 IPoint p1(1, 2);
696 Point p2 = p1 * Point(2, 3);
697 ASSERT_FLOAT_EQ(p2.x, 2u);
698 ASSERT_FLOAT_EQ(p2.y, 6u);
699 }
700
701 {
702 IPoint p1(2, 6);
703 Point p2 = p1 / Point(2, 3);
704 ASSERT_FLOAT_EQ(p2.x, 1u);
705 ASSERT_FLOAT_EQ(p2.y, 2u);
706 }
707
708 // Float on LHS, integer on RHS
709 {
710 Point p1(1, 2);
711 Point p2 = p1 + IPoint(1, 2);
712 ASSERT_FLOAT_EQ(p2.x, 2u);
713 ASSERT_FLOAT_EQ(p2.y, 4u);
714 }
715
716 {
717 Point p1(3, 6);
718 Point p2 = p1 - IPoint(1, 2);
719 ASSERT_FLOAT_EQ(p2.x, 2u);
720 ASSERT_FLOAT_EQ(p2.y, 4u);
721 }
722
723 {
724 Point p1(1, 2);
725 Point p2 = p1 * IPoint(2, 3);
726 ASSERT_FLOAT_EQ(p2.x, 2u);
727 ASSERT_FLOAT_EQ(p2.y, 6u);
728 }
729
730 {
731 Point p1(2, 6);
732 Point p2 = p1 / IPoint(2, 3);
733 ASSERT_FLOAT_EQ(p2.x, 1u);
734 ASSERT_FLOAT_EQ(p2.y, 2u);
735 }
736 }

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

## ◆ TEST() [147/389]

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

Definition at line 1109 of file geometry_unittests.cc.

1109 {
1110 Point p(1, 2);
1111 Point result = p.Lerp({5, 10}, 0.75);
1112 Point expected(4, 8);
1113 ASSERT_POINT_NEAR(result, expected);
1114 }

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

## ◆ TEST() [148/389]

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

Definition at line 1025 of file geometry_unittests.cc.

1025 {
1026 Point p(1, 2);
1027 Point result = p.Max({0, 10});
1028 Point expected(1, 10);
1029 ASSERT_POINT_NEAR(result, expected);
1030 }

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

## ◆ TEST() [149/389]

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

Definition at line 1004 of file geometry_unittests.cc.

1004 {
1005 Point p(1, 2);
1006 Point result = p.Min({0, 10});
1007 Point expected(0, 2);
1008 ASSERT_POINT_NEAR(result, expected);
1009 }

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

## ◆ TEST() [150/389]

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

Definition at line 1707 of file geometry_unittests.cc.

1707 {
1708 {
1709 std::stringstream stream;
1710 Point m;
1711 stream << m;
1712 ASSERT_EQ(stream.str(), "(0, 0)");
1713 }
1714
1715 {
1716 std::stringstream stream;
1717 Point m(13, 37);
1718 stream << m;
1719 ASSERT_EQ(stream.str(), "(13, 37)");
1720 }
1721 }

## ◆ TEST() [151/389]

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

Definition at line 913 of file geometry_unittests.cc.

913 {
914 {
915 Point axis = Point(0, 1);
916 Point a(2, 3);
917 auto reflected = a.Reflect(axis);
918 auto expected = Point(2, -3);
919 ASSERT_POINT_NEAR(reflected, expected);
920 }
921
922 {
923 Point axis = Point(1, 1).Normalize();
924 Point a(1, 0);
925 auto reflected = a.Reflect(axis);
926 auto expected = Point(0, -1);
927 ASSERT_POINT_NEAR(reflected, expected);
928 }
929
930 {
931 Point axis = Point(1, 1).Normalize();
932 Point a(-1, -1);
933 auto reflected = a.Reflect(axis);
934 ASSERT_POINT_NEAR(reflected, -a);
935 }
936 }

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

## ◆ TEST() [152/389]

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

Definition at line 945 of file geometry_unittests.cc.

945 {
946 {
947 Point a(1, 0);
948 auto rotated = a.Rotate(Radians{kPiOver2});
949 auto expected = Point(0, 1);
950 ASSERT_POINT_NEAR(rotated, expected);
951 }
952
953 {
954 Point a(1, 0);
955 auto rotated = a.Rotate(Radians{-kPiOver2});
956 auto expected = Point(0, -1);
957 ASSERT_POINT_NEAR(rotated, expected);
958 }
959
960 {
961 Point a(1, 0);
962 auto rotated = a.Rotate(Radians{kPi});
963 auto expected = Point(-1, 0);
964 ASSERT_POINT_NEAR(rotated, expected);
965 }
966
967 {
968 Point a(1, 0);
969 auto rotated = a.Rotate(Radians{kPi * 1.5});
970 auto expected = Point(0, -1);
971 ASSERT_POINT_NEAR(rotated, expected);
972 }
973 }

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

## ◆ TEST() [153/389]

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

Definition at line 1088 of file geometry_unittests.cc.

1088 {
1089 Point p(1.5, 2.3);
1090 Point result = p.Round();
1091 Point expected(2, 2);
1092 ASSERT_POINT_NEAR(result, expected);
1093 }

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

## ◆ TEST() [154/389]

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

Definition at line 527 of file geometry_unittests.cc.

527 {
528 auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0};
529 auto q2 = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
530
531 auto q3 = q1.Slerp(q2, 0.5);
532
533 auto expected = Quaternion{{0.0, 0.0, 1.0}, kPiOver4 / 2.0};
534
535 ASSERT_QUATERNION_NEAR(q3, expected);
536 }

References ASSERT_QUATERNION_NEAR, and impeller::kPiOver4.

## ◆ TEST() [155/389]

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

Definition at line 538 of file geometry_unittests.cc.

538 {
539 {
540 Quaternion q({0, 0, 1}, 0);
541 Vector3 v(0, 1, 0);
542
543 Vector3 result = q * v;
544 Vector3 expected(0, 1, 0);
545
546 ASSERT_VECTOR3_NEAR(result, expected);
547 }
548
549 {
550 Quaternion q({0, 0, 1}, k2Pi);
551 Vector3 v(1, 0, 0);
552
553 Vector3 result = q * v;
554 Vector3 expected(1, 0, 0);
555
556 ASSERT_VECTOR3_NEAR(result, expected);
557 }
558
559 {
560 Quaternion q({0, 0, 1}, kPiOver4);
561 Vector3 v(0, 1, 0);
562
563 Vector3 result = q * v;
564 Vector3 expected(-k1OverSqrt2, k1OverSqrt2, 0);
565
566 ASSERT_VECTOR3_NEAR(result, expected);
567 }
568
569 {
570 Quaternion q(Vector3(1, 0, 1).Normalize(), kPi);
571 Vector3 v(0, 0, -1);
572
573 Vector3 result = q * v;
574 Vector3 expected(-1, 0, 0);
575
576 ASSERT_VECTOR3_NEAR(result, expected);
577 }
578 }

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

## ◆ TEST() [156/389]

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() [157/389]

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() [158/389]

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

Definition at line 1164 of file geometry_unittests.cc.

1164 {
1165 {
1166 SeparatedVector2 v(Vector2(10, 0));
1167 Radians actual = v.AngleTo(SeparatedVector2(Vector2(5, 0)));
1168 Radians expected = Radians{0};
1169 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1170 }
1171
1172 {
1173 SeparatedVector2 v(Vector2(10, 0));
1174 Radians actual = v.AngleTo(SeparatedVector2(Vector2(0, -5)));
1175 Radians expected = Radians{-kPi / 2};
1176 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1177 }
1178 }

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

## ◆ TEST() [159/389]

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

Definition at line 1141 of file geometry_unittests.cc.

1141 {
1142 // Parallel
1143 {
1144 SeparatedVector2 v(Vector2(10, 0));
1145 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(5, 0)));
1146 ASSERT_NEAR(actual, 1, kEhCloseEnough);
1147 }
1148
1149 // Perpendicular
1150 {
1151 SeparatedVector2 v(Vector2(10, 0));
1152 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, 5)));
1153 ASSERT_NEAR(actual, 0, kEhCloseEnough);
1154 }
1155
1156 // Opposite parallel
1157 {
1158 SeparatedVector2 v(Vector2(0, 10));
1159 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, -5)));
1160 ASSERT_NEAR(actual, -1, kEhCloseEnough);
1161 }
1162 }

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

## ◆ TEST() [160/389]

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

Definition at line 1136 of file geometry_unittests.cc.

1136 {
1137 SeparatedVector2 v(Vector2(10, 0));
1138 ASSERT_POINT_NEAR(v.GetVector(), Vector2(10, 0));
1139 }

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

## ◆ TEST() [161/389]

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

Definition at line 1130 of file geometry_unittests.cc.

1130 {
1131 SeparatedVector2 v(Vector2(10, 0));
1132 ASSERT_POINT_NEAR(v.direction, Vector2(1, 0));
1133 ASSERT_NEAR(v.magnitude, 10, kEhCloseEnough);
1134 }

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

## ◆ TEST() [162/389]

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

Definition at line 738 of file geometry_unittests.cc.

738 {
739 // Point on LHS, Size on RHS
740 {
741 IPoint p1(1, 2);
742 IPoint p2 = p1 + ISize(1, 2);
743 ASSERT_EQ(p2.x, 2u);
744 ASSERT_EQ(p2.y, 4u);
745 }
746
747 {
748 IPoint p1(3, 6);
749 IPoint p2 = p1 - ISize(1, 2);
750 ASSERT_EQ(p2.x, 2u);
751 ASSERT_EQ(p2.y, 4u);
752 }
753
754 {
755 IPoint p1(1, 2);
756 IPoint p2 = p1 * ISize(2, 3);
757 ASSERT_EQ(p2.x, 2u);
758 ASSERT_EQ(p2.y, 6u);
759 }
760
761 {
762 IPoint p1(2, 6);
763 IPoint p2 = p1 / ISize(2, 3);
764 ASSERT_EQ(p2.x, 1u);
765 ASSERT_EQ(p2.y, 2u);
766 }
767
768 // Size on LHS, Point on RHS
769 {
770 ISize p1(1, 2);
771 IPoint p2 = p1 + IPoint(1, 2);
772 ASSERT_EQ(p2.x, 2u);
773 ASSERT_EQ(p2.y, 4u);
774 }
775
776 {
777 ISize p1(3, 6);
778 IPoint p2 = p1 - IPoint(1, 2);
779 ASSERT_EQ(p2.x, 2u);
780 ASSERT_EQ(p2.y, 4u);
781 }
782
783 {
784 ISize p1(1, 2);
785 IPoint p2 = p1 * IPoint(2, 3);
786 ASSERT_EQ(p2.x, 2u);
787 ASSERT_EQ(p2.y, 6u);
788 }
789
790 {
791 ISize p1(2, 6);
792 IPoint p2 = p1 / IPoint(2, 3);
793 ASSERT_EQ(p2.x, 1u);
794 ASSERT_EQ(p2.y, 2u);
795 }
796 }

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

## ◆ TEST() [163/389]

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() [164/389]

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() [165/389]

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() [166/389]

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() [167/389]

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

Definition at line 1771 of file geometry_unittests.cc.

1771 {
1772 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
1773 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
1774 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
1775 }

References impeller::Color::ToIColor().

## ◆ TEST() [168/389]

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

Definition at line 1074 of file geometry_unittests.cc.

1074 {
1075 Vector3 p(1.5, 2.3, 3.9);
1076 Vector3 result = p.Ceil();
1077 Vector3 expected(2, 3, 4);
1078 ASSERT_VECTOR3_NEAR(result, expected);
1079 }

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

## ◆ TEST() [169/389]

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

Definition at line 1053 of file geometry_unittests.cc.

1053 {
1054 Vector3 p(1.5, 2.3, 3.9);
1055 Vector3 result = p.Floor();
1056 Vector3 expected(1, 2, 3);
1057 ASSERT_VECTOR3_NEAR(result, expected);
1058 }

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

## ◆ TEST() [170/389]

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

Definition at line 1116 of file geometry_unittests.cc.

1116 {
1117 Vector3 p(1, 2, 3);
1118 Vector3 result = p.Lerp({5, 10, 15}, 0.75);
1119 Vector3 expected(4, 8, 12);
1120 ASSERT_VECTOR3_NEAR(result, expected);
1121 }

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

## ◆ TEST() [171/389]

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

Definition at line 1032 of file geometry_unittests.cc.

1032 {
1033 Vector3 p(1, 2, 3);
1034 Vector3 result = p.Max({0, 10, 2});
1035 Vector3 expected(1, 10, 3);
1036 ASSERT_VECTOR3_NEAR(result, expected);
1037 }

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

## ◆ TEST() [172/389]

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

Definition at line 1011 of file geometry_unittests.cc.

1011 {
1012 Vector3 p(1, 2, 3);
1013 Vector3 result = p.Min({0, 10, 2});
1014 Vector3 expected(0, 2, 2);
1015 ASSERT_VECTOR3_NEAR(result, expected);
1016 }

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

## ◆ TEST() [173/389]

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

Definition at line 1723 of file geometry_unittests.cc.

1723 {
1724 {
1725 std::stringstream stream;
1726 Vector3 m;
1727 stream << m;
1728 ASSERT_EQ(stream.str(), "(0, 0, 0)");
1729 }
1730
1731 {
1732 std::stringstream stream;
1733 Vector3 m(1, 2, 3);
1734 stream << m;
1735 ASSERT_EQ(stream.str(), "(1, 2, 3)");
1736 }
1737 }

## ◆ TEST() [174/389]

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

Definition at line 1095 of file geometry_unittests.cc.

1095 {
1096 Vector3 p(1.5, 2.3, 3.9);
1097 Vector3 result = p.Round();
1098 Vector3 expected(2, 2, 4);
1099 ASSERT_VECTOR3_NEAR(result, expected);
1100 }

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

## ◆ TEST() [175/389]

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

Definition at line 1081 of file geometry_unittests.cc.

1081 {
1082 Vector4 p(1.5, 2.3, 3.9, 4.0);
1083 Vector4 result = p.Ceil();
1084 Vector4 expected(2, 3, 4, 4);
1085 ASSERT_VECTOR4_NEAR(result, expected);
1086 }

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

## ◆ TEST() [176/389]

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

Definition at line 1060 of file geometry_unittests.cc.

1060 {
1061 Vector4 p(1.5, 2.3, 3.9, 4.0);
1062 Vector4 result = p.Floor();
1063 Vector4 expected(1, 2, 3, 4);
1064 ASSERT_VECTOR4_NEAR(result, expected);
1065 }

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

## ◆ TEST() [177/389]

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

Definition at line 1123 of file geometry_unittests.cc.

1123 {
1124 Vector4 p(1, 2, 3, 4);
1125 Vector4 result = p.Lerp({5, 10, 15, 20}, 0.75);
1126 Vector4 expected(4, 8, 12, 16);
1127 ASSERT_VECTOR4_NEAR(result, expected);
1128 }

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

## ◆ TEST() [178/389]

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

Definition at line 1039 of file geometry_unittests.cc.

1039 {
1040 Vector4 p(1, 2, 3, 4);
1041 Vector4 result = p.Max({0, 10, 2, 1});
1042 Vector4 expected(1, 10, 3, 4);
1043 ASSERT_VECTOR4_NEAR(result, expected);
1044 }

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

## ◆ TEST() [179/389]

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

Definition at line 1018 of file geometry_unittests.cc.

1018 {
1019 Vector4 p(1, 2, 3, 4);
1020 Vector4 result = p.Min({0, 10, 2, 1});
1021 Vector4 expected(0, 2, 2, 1);
1022 ASSERT_VECTOR4_NEAR(result, expected);
1023 }

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

## ◆ TEST() [180/389]

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

Definition at line 1739 of file geometry_unittests.cc.

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

## ◆ TEST() [181/389]

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

Definition at line 1102 of file geometry_unittests.cc.

1102 {
1103 Vector4 p(1.5, 2.3, 3.9, 4.0);
1104 Vector4 result = p.Round();
1105 Vector4 expected(2, 2, 4, 4);
1106 ASSERT_VECTOR4_NEAR(result, expected);
1107 }

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

## ◆ TEST() [182/389]

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() [183/389]

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() [184/389]

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() [185/389]

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() [186/389]

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() [187/389]

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

Definition at line 28 of file matrix_unittests.cc.

28 {
29 Matrix x;
30 Matrix y = x;
31 EXPECT_TRUE(x.Equals(y));
32 }

References impeller::Matrix::Equals().

## ◆ TEST() [188/389]

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

Definition at line 176 of file matrix_unittests.cc.

176 {
177 Matrix m = Matrix::MakeScale({-2, 1, 1});
178
179 EXPECT_EQ(m.GetMaxBasisLengthXY(), 2);
180
181 m = Matrix::MakeScale({1, -3, 1});
182
183 EXPECT_EQ(m.GetMaxBasisLengthXY(), 3);
184 }

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

## ◆ TEST() [189/389]

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

Definition at line 187 of file matrix_unittests.cc.

187 {
188 Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
189 EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e+20, 1e+20);
190
191 m = Matrix::MakeScale({2.625e-20, 2.625e-20, 1});
192 EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e-20, 1e-20);
193 }

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

## ◆ TEST() [190/389]

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

Definition at line 195 of file matrix_unittests.cc.

195 {
196 Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
197 m.e[0][1] = 2;
198
199 EXPECT_TRUE(std::isinf(m.GetMaxBasisLengthXY()));
200 }

References impeller::Matrix::e, impeller::Matrix::GetMaxBasisLengthXY(), and impeller::Matrix::MakeScale().

## ◆ TEST() [191/389]

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

Definition at line 58 of file matrix_unittests.cc.

58 {
59 EXPECT_FALSE(Matrix().HasPerspective());
60
61 auto test = [](int index, bool expect) {
62 Matrix matrix;
63 EXPECT_FALSE(matrix.HasPerspective());
64 matrix.m[index] = 0.5f;
65 EXPECT_EQ(matrix.HasPerspective(), expect) << "index: " << index;
66 };
67
68 // clang-format off
69 test( 0, false); test( 1, false); test( 2, false); test( 3, true);
70 test( 4, false); test( 5, false); test( 6, false); test( 7, true);
71 test( 8, false); test( 9, false); test(10, false); test(11, true);
72 test(12, false); test(13, false); test(14, false); test(15, true);
73 // clang-format on
74 }

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

## ◆ TEST() [192/389]

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

Definition at line 40 of file matrix_unittests.cc.

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

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

## ◆ TEST() [193/389]

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

Definition at line 76 of file matrix_unittests.cc.

76 {
77 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).HasTranslation());
78 EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).HasTranslation());
79 EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).HasTranslation());
80 EXPECT_FALSE(Matrix().HasTranslation());
81 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [194/389]

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

Definition at line 116 of file matrix_unittests.cc.

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

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

## ◆ TEST() [195/389]

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

Definition at line 83 of file matrix_unittests.cc.

83 {
84 EXPECT_TRUE(Matrix().IsAligned2D());
85 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
86
87 auto test = [](int index, bool expect) {
88 Matrix matrix;
89 EXPECT_TRUE(matrix.IsAligned2D());
90 matrix.m[index] = 0.5f;
91 EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
92 };
93
94 // clang-format off
95 test( 0, true); test( 1, false); test( 2, true); test( 3, false);
96 test( 4, false); test( 5, true); test( 6, true); test( 7, false);
97 test( 8, true); test( 9, true); test(10, true); test(11, true);
98 test(12, true); test(13, true); test(14, true); test(15, false);
99 // clang-format on
100
101 // True for quadrant rotations from -250 to +250 full circles
102 for (int i = -1000; i < 1000; i++) {
103 Degrees d = Degrees(i * 90);
104 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
105 EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
106 }
107
108 // False for half degree rotations from -999.5 to +1000.5 degrees
109 for (int i = -1000; i < 1000; i++) {
110 Degrees d = Degrees(i + 0.5f);
111 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
112 EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
113 }
114 }

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

## ◆ TEST() [196/389]

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

Definition at line 15 of file matrix_unittests.cc.

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

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

## ◆ TEST() [197/389]

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

Definition at line 34 of file matrix_unittests.cc.

34 {
35 Matrix x;
36 Matrix y = x.Translate({1, 0, 0});
37 EXPECT_FALSE(x.Equals(y));
38 }

References impeller::Matrix::Equals(), and impeller::Matrix::Translate().

## ◆ TEST() [198/389]

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

Definition at line 163 of file matrix_unittests.cc.

163 {
164 Matrix matrix = Matrix::MakeColumn(
165 // clang-format off
166 2.0f, 3.0f, 5.0f, 7.0f,
167 11.0f, 13.0f, 17.0f, 19.0f,
168 23.0f, 29.0f, 31.0f, 37.0f,
169 41.0f, 43.0f, 47.0f, 53.0f
170 // clang-format on
171 );
172 EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
173 Vector3(32.0f, 33.0f, 41.0f));
174 }

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

## ◆ TEST() [199/389]

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

Definition at line 202 of file matrix_unittests.cc.

202 {
203 Matrix m = Matrix::MakeRow(1.0, 0.0, 0.0, 10.0, //
204 0.0, 1.0, 0.0, 20.0, //
205 0.0, 0.0, 1.0, 0.0, //
206 0.0, 2.0, 0.0, 30.0);
207 Matrix result = m.Translate({100, 200});
208 EXPECT_TRUE(MatrixNear(result, Matrix::MakeRow(1.0, 0.0, 0.0, 110.0, //
209 0.0, 1.0, 0.0, 220.0, //
210 0.0, 0.0, 1.0, 0.0, //
211 0.0, 2.0, 0.0, 430.0)));
212 }

References impeller::Matrix::MakeRow(), MatrixNear(), and impeller::Matrix::Translate().

## ◆ TEST() [200/389]

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

Definition at line 347 of file path_unittests.cc.

347 {
348 PathBuilder builder;
349 auto path =
350 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
351 .TakePath();
352 auto box = path.GetBoundingBox();
353 Rect expected = Rect::MakeXYWH(93.9101, 40, 126.09, 158.862);
354 ASSERT_TRUE(box.has_value());
355 ASSERT_RECT_NEAR(box.value_or(Rect::MakeMaximum()), expected);
356 }

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

## ◆ TEST() [201/389]

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

Definition at line 358 of file path_unittests.cc.

358 {
359 PathBuilder builder;
360 builder.AddRoundedRect(Rect::MakeXYWH(10, 10, 300, 300), {50, 50, 50, 50});
361 auto path = builder.TakePath();
362 auto actual = path.GetBoundingBox();
363 Rect expected = Rect::MakeXYWH(10, 10, 300, 300);
364
365 ASSERT_TRUE(actual.has_value());
366 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
367 }

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

## ◆ TEST() [202/389]

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

Definition at line 527 of file path_unittests.cc.

527 {
528 PathBuilder builder;
529 builder.MoveTo({10, 10});
530 builder.LineTo({20, 20});
531 builder.SetBounds(Rect::MakeLTRB(0, 0, 100, 100));
532 builder.SetConvexity(Convexity::kConvex);
533
534 auto path_a = builder.TakePath(FillType::kOdd);
535 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
536 auto path_b = path_a;
537
538 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
539 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
540 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
541
542 auto poly_a = path_a.CreatePolyline(1.0);
543 auto poly_b = path_b.CreatePolyline(1.0);
544
545 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
546 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
547
548 for (auto i = 0u; i < poly_a.points->size(); i++) {
549 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
550 }
551
552 for (auto i = 0u; i < poly_a.contours.size(); i++) {
553 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
554 EXPECT_EQ(poly_a.contours[i].start_direction,
555 poly_b.contours[i].start_direction);
556 }
557 }

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() [203/389]

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

Definition at line 497 of file path_unittests.cc.

497 {
498 PathBuilder builder;
499 auto path = builder.LineTo({0, 10})
500 .LineTo({10, 10})
501 .MoveTo({30, 30}) // Moves to (30, 30)
502 .Close() // No Op
503 .Close() // Still No op
504 .TakePath();
505
506 EXPECT_EQ(path.GetComponentCount(), 4u);
507 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 2u);
508 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
509 }

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

## ◆ TEST() [204/389]

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

Definition at line 511 of file path_unittests.cc.

511 {
512 PathBuilder builder;
513 // Create a path that has a current position at the origin when close is
514 // called. This should not insert a new line segment
515 auto path = builder.LineTo({10, 0})
516 .LineTo({10, 10})
517 .LineTo({0, 10})
518 .LineTo({0, 0})
519 .Close()
520 .TakePath();
521
522 EXPECT_EQ(path.GetComponentCount(), 6u);
523 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 4u);
524 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
525 }

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

## ◆ TEST() [205/389]

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

Definition at line 332 of file path_unittests.cc.

332 {
333 PathBuilder builder;
334 auto path =
335 builder.CubicCurveTo(Point(10, 10), Point(-10, -10), Point(20, 20))
336 .TakePath();
337
338 CubicPathComponent cubic;
339 path.GetCubicComponentAtIndex(1, cubic);
340
341 EXPECT_EQ(cubic.p1, Point(0, 0));
342 EXPECT_EQ(cubic.cp1, Point(10, 10));
343 EXPECT_EQ(cubic.cp2, Point(-10, -10));
344 EXPECT_EQ(cubic.p2, Point(20, 20));
345 }

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

## ◆ TEST() [206/389]

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

Definition at line 16 of file path_unittests.cc.

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

References polyline.

## ◆ TEST() [207/389]

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

Definition at line 392 of file path_unittests.cc.

392 {
393 auto path = PathBuilder{}.TakePath();
394 ASSERT_EQ(path.GetComponentCount(), 1u);
395
396 ContourComponent c;
397 path.GetContourComponentAtIndex(0, c);
398 ASSERT_POINT_NEAR(c.destination, Point());
399
400 Path::Polyline polyline = path.CreatePolyline(1.0f);
401 ASSERT_TRUE(polyline.points->empty());
402 ASSERT_TRUE(polyline.contours.empty());
403 }

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

## ◆ TEST() [208/389]

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

Definition at line 26 of file path_unittests.cc.

26 {
27 PathBuilder builder;
28 auto path = builder.TakePath();
29
30 EXPECT_TRUE(path.IsEmpty());
31 }

References impeller::PathBuilder::TakePath().

## ◆ TEST() [209/389]

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

Definition at line 369 of file path_unittests.cc.

369 {
370 CubicPathComponent cubic{{11.769268, 252.883148},
371 {-6.2857933, 204.356461},
372 {-4.53997231, 156.552902},
373 {17.0067291, 109.472488}};
374 auto points = cubic.Extrema();
375
376 ASSERT_EQ(points.size(), static_cast<size_t>(3));
377 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
378 }

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

## ◆ TEST() [210/389]

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

Definition at line 168 of file path_unittests.cc.

168 {
169 Path::Polyline polyline = PathBuilder{}
170 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
171 .TakePath()
172 .CreatePolyline(1.0f);
173 ASSERT_EQ(polyline.contours.size(), 1u);
174 ASSERT_TRUE(polyline.contours[0].is_closed);
175 ASSERT_EQ(polyline.contours[0].start_index, 0u);
176 ASSERT_EQ(polyline.points->size(), 5u);
177 ASSERT_EQ(polyline.GetPoint(0), Point(50, 60));
178 ASSERT_EQ(polyline.GetPoint(1), Point(70, 60));
179 ASSERT_EQ(polyline.GetPoint(2), Point(70, 80));
180 ASSERT_EQ(polyline.GetPoint(3), Point(50, 80));
181 ASSERT_EQ(polyline.GetPoint(4), Point(50, 60));
182 }

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

## ◆ TEST() [211/389]

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

Definition at line 559 of file path_unittests.cc.

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

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::IsClosed(), 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() [212/389]

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

Definition at line 52 of file path_unittests.cc.

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

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::IsClosed(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [213/389]

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

Definition at line 276 of file path_unittests.cc.

276 {
277 PathBuilder builder;
278 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
279
280 ASSERT_EQ(path_1.GetBoundingBox().value_or(Rect::MakeMaximum()),
281 Rect::MakeLTRB(0, 0, 1, 1));
282
283 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
284
285 // Verify that PathBuilder recomputes the bounds.
286 ASSERT_EQ(path_2.GetBoundingBox().value_or(Rect::MakeMaximum()),
287 Rect::MakeLTRB(-1, -1, 1, 1));
288
289 // PathBuilder can set the bounds to whatever it wants
290 auto path_3 = builder.AddLine({0, 0}, {1, 1})
291 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
292 .TakePath();
293
294 ASSERT_EQ(path_3.GetBoundingBox().value_or(Rect::MakeMaximum()),
295 Rect::MakeLTRB(0, 0, 100, 100));
296 }

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

## ◆ TEST() [214/389]

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

Definition at line 33 of file path_unittests.cc.

33 {
34 PathBuilder builder;
35 builder.MoveTo({10, 10});
36 builder.LineTo({20, 20});
37 builder.LineTo({30, 30});
38 builder.MoveTo({40, 40});
39 builder.LineTo({50, 50});
40
41 auto polyline = builder.TakePath().CreatePolyline(1.0f);
42
43 ASSERT_EQ(polyline.contours.size(), 2u);
44 ASSERT_EQ(polyline.points->size(), 5u);
45 ASSERT_EQ(polyline.GetPoint(0).x, 10);
46 ASSERT_EQ(polyline.GetPoint(1).x, 20);
47 ASSERT_EQ(polyline.GetPoint(2).x, 30);
48 ASSERT_EQ(polyline.GetPoint(3).x, 40);
49 ASSERT_EQ(polyline.GetPoint(4).x, 50);
50 }

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

## ◆ TEST() [215/389]

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

Definition at line 133 of file path_unittests.cc.

133 {
134 Path::Polyline polyline = PathBuilder{}
135 .AddLine({100, 100}, {200, 100})
136 .MoveTo({100, 200})
137 .LineTo({150, 250})
138 .LineTo({200, 200})
139 .Close()
140 .TakePath()
141 .CreatePolyline(1.0f);
142 ASSERT_EQ(polyline.points->size(), 6u);
143 ASSERT_EQ(polyline.contours.size(), 2u);
144 ASSERT_EQ(polyline.contours[0].is_closed, false);
145 ASSERT_EQ(polyline.contours[0].start_index, 0u);
146 ASSERT_EQ(polyline.contours[1].is_closed, true);
147 ASSERT_EQ(polyline.contours[1].start_index, 2u);
148 }

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

## ◆ TEST() [216/389]

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

Definition at line 380 of file path_unittests.cc.

380 {
381 PathBuilder builder;
382 // Straight diagonal line.
383 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
384 auto path = builder.TakePath();
385 auto actual = path.GetBoundingBox();
386 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
387
388 ASSERT_TRUE(actual.has_value());
389 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
390 }

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

## ◆ TEST() [217/389]

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

Definition at line 298 of file path_unittests.cc.

298 {
299 PathBuilder builder;
300 auto path = builder.HorizontalLineTo(10).TakePath();
301
302 LinearPathComponent linear;
303 path.GetLinearComponentAtIndex(1, linear);
304
305 EXPECT_EQ(linear.p1, Point(0, 0));
306 EXPECT_EQ(linear.p2, Point(10, 0));
307 }

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

## ◆ TEST() [218/389]

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

Definition at line 184 of file path_unittests.cc.

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

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

## ◆ TEST() [219/389]

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

Definition at line 240 of file path_unittests.cc.

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

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() [220/389]

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

Definition at line 309 of file path_unittests.cc.

309 {
310 PathBuilder builder;
311 auto path = builder.VerticalLineTo(10).TakePath();
312
313 LinearPathComponent linear;
314 path.GetLinearComponentAtIndex(1, linear);
315
316 EXPECT_EQ(linear.p1, Point(0, 0));
317 EXPECT_EQ(linear.p2, Point(0, 10));
318 }

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

## ◆ TEST() [221/389]

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

Definition at line 213 of file path_unittests.cc.

213 {
214 auto point_buffer = std::make_unique<std::vector<Point>>();
215 auto point_buffer_address = reinterpret_cast<uintptr_t>(point_buffer.get());
216 Path::Polyline polyline =
217 PathBuilder{}
218 .MoveTo({50, 50})
219 .LineTo({100, 100})
220 .TakePath()
221 .CreatePolyline(
222 1.0f, std::move(point_buffer),
223 [point_buffer_address](
224 Path::Polyline::PointBufferPtr point_buffer) {
225 ASSERT_EQ(point_buffer->size(), 0u);
226 ASSERT_EQ(point_buffer_address,
227 reinterpret_cast<uintptr_t>(point_buffer.get()));
228 });
229 }

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

## ◆ TEST() [222/389]

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

Definition at line 231 of file path_unittests.cc.

231 {
232 EXPECT_DEATH_IF_SUPPORTED(PathBuilder{}
233 .MoveTo({50, 50})
234 .LineTo({100, 100})
235 .TakePath()
236 .CreatePolyline(1.0f, nullptr),
237 "");
238 }

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

## ◆ TEST() [223/389]

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

Definition at line 150 of file path_unittests.cc.

150 {
151 Path::Polyline polyline = PathBuilder{}
152 .AddLine({100, 100}, {200, 100})
153 .MoveTo({100, 200})
154 .LineTo({150, 250})
155 .LineTo({200, 200})
156 .Close()
157 .TakePath()
158 .CreatePolyline(1.0f);
159 size_t a1, a2, b1, b2;
160 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
161 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
162 ASSERT_EQ(a1, 0u);
163 ASSERT_EQ(a2, 2u);
164 ASSERT_EQ(b1, 2u);
165 ASSERT_EQ(b2, 6u);
166 }

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

## ◆ TEST() [224/389]

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

Definition at line 320 of file path_unittests.cc.

320 {
321 PathBuilder builder;
322 auto path = builder.QuadraticCurveTo(Point(10, 10), Point(20, 20)).TakePath();
323
324 QuadraticPathComponent quad;
325 path.GetQuadraticComponentAtIndex(1, quad);
326
327 EXPECT_EQ(quad.p1, Point(0, 0));
328 EXPECT_EQ(quad.cp, Point(10, 10));
329 EXPECT_EQ(quad.p2, Point(20, 20));
330 }

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

## ◆ TEST() [225/389]

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

Definition at line 483 of file path_unittests.cc.

483 {
484 PathBuilder builder;
485 auto path = builder.LineTo({0, 10})
486 .LineTo({10, 10})
487 .Close() // Returns to (0, 0)
488 .Close() // No Op
489 .Close() // Still No op
490 .TakePath();
491
492 EXPECT_EQ(path.GetComponentCount(), 5u);
493 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 3u);
494 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
495 }

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

## ◆ TEST() [226/389]

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

Definition at line 405 of file path_unittests.cc.

405 {
406 PathBuilder builder;
407
408 auto path = builder.AddLine({0, 0}, {100, 100})
409 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
410 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
411 .TakePath();
412
413 EXPECT_EQ(path.GetComponentCount(), 6u);
414 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
415 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
416 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
417 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 3u);
418
419 {
420 LinearPathComponent linear;
421 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, linear));
422
423 Point p1(0, 0);
424 Point p2(100, 100);
425 EXPECT_EQ(linear.p1, p1);
426 EXPECT_EQ(linear.p2, p2);
427 }
428
429 {
430 QuadraticPathComponent quad;
431 EXPECT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
432
433 Point p1(100, 100);
434 Point cp(200, 200);
435 Point p2(300, 300);
436 EXPECT_EQ(quad.p1, p1);
437 EXPECT_EQ(quad.cp, cp);
438 EXPECT_EQ(quad.p2, p2);
439 }
440
441 {
442 CubicPathComponent cubic;
443 EXPECT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
444
445 Point p1(300, 300);
446 Point cp1(400, 400);
447 Point cp2(500, 500);
448 Point p2(600, 600);
449 EXPECT_EQ(cubic.p1, p1);
450 EXPECT_EQ(cubic.cp1, cp1);
451 EXPECT_EQ(cubic.cp2, cp2);
452 EXPECT_EQ(cubic.p2, p2);
453 }
454
455 {
456 ContourComponent contour;
457 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour));
458
459 Point p1(0, 0);
460 EXPECT_EQ(contour.destination, p1);
461 EXPECT_FALSE(contour.IsClosed());
462 }
463
464 {
465 ContourComponent contour;
466 EXPECT_TRUE(path.GetContourComponentAtIndex(2, contour));
467
468 Point p1(100, 100);
469 EXPECT_EQ(contour.destination, p1);
470 EXPECT_FALSE(contour.IsClosed());
471 }
472
473 {
474 ContourComponent contour;
475 EXPECT_TRUE(path.GetContourComponentAtIndex(4, contour));
476
477 Point p1(300, 300);
478 EXPECT_EQ(contour.destination, p1);
479 EXPECT_FALSE(contour.IsClosed());
480 }
481 }

References impeller::PathBuilder::AddLine(), impeller::QuadraticPathComponent::cp, impeller::CubicPathComponent::cp1, impeller::CubicPathComponent::cp2, impeller::ContourComponent::destination, impeller::ContourComponent::IsClosed(), impeller::Path::kContour, impeller::Path::kCubic, impeller::Path::kLinear, impeller::Path::kQuadratic, impeller::LinearPathComponent::p1, impeller::QuadraticPathComponent::p1, impeller::CubicPathComponent::p1, impeller::LinearPathComponent::p2, impeller::QuadraticPathComponent::p2, and impeller::CubicPathComponent::p2.

## ◆ TEST() [227/389]

impeller::testing::TEST | ( | PipelineCacheDataVKTest | ,
|  | CanCreateFromDeviceProperties |
| ) |  |

Definition at line 76 of file pipeline_cache_data_vk_unittests.cc.

76 {
77 vk::PhysicalDeviceProperties props;
78 std::array<uint8_t, 16> uuid{
79 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
80 };
81 props.pipelineCacheUUID = uuid;
82 props.deviceID = 10;
83 props.vendorID = 11;
84 props.driverVersion = 12;
85 PipelineCacheHeaderVK header(props, 99);
86 EXPECT_EQ(uuid.size(), std::size(header.uuid));
87 EXPECT_EQ(props.deviceID, header.device_id);
88 EXPECT_EQ(props.vendorID, header.vendor_id);
89 EXPECT_EQ(props.driverVersion, header.driver_version);
90 for (size_t i = 0; i < uuid.size(); i++) {
91 EXPECT_EQ(header.uuid[i], uuid.at(i));
92 }
93 }

References impeller::PipelineCacheHeaderVK::device_id, impeller::PipelineCacheHeaderVK::driver_version, impeller::PipelineCacheHeaderVK::uuid, and impeller::PipelineCacheHeaderVK::vendor_id.

## ◆ TEST() [228/389]

impeller::testing::TEST | ( | PipelineCacheDataVKTest | ,
|  | CanTestHeaderCompatibility |
| ) |  |

Definition at line 16 of file pipeline_cache_data_vk_unittests.cc.

16 {
17 {
18 PipelineCacheHeaderVK a;
19 PipelineCacheHeaderVK b;
20 EXPECT_EQ(a.abi, sizeof(void*));
21 #ifdef FML_ARCH_CPU_64_BITS
22 EXPECT_EQ(a.abi, 8u);
23 #elif FML_ARCH_CPU_32_BITS
24 EXPECT_EQ(a.abi, 4u);
25 #endif
26 EXPECT_TRUE(a.IsCompatibleWith(b));
27 }
28 // Different data sizes don't matter.
29 {
30 PipelineCacheHeaderVK a;
31 PipelineCacheHeaderVK b;
32 a.data_size = b.data_size + 100u;
33 EXPECT_TRUE(a.IsCompatibleWith(b));
34 }
35 // Magic, Driver, vendor, ABI, and UUID matter.
36 {
37 PipelineCacheHeaderVK a;
38 PipelineCacheHeaderVK b;
39 b.magic = 100;
40 EXPECT_FALSE(a.IsCompatibleWith(b));
41 }
42 {
43 PipelineCacheHeaderVK a;
44 PipelineCacheHeaderVK b;
45 b.driver_version = 100;
46 EXPECT_FALSE(a.IsCompatibleWith(b));
47 }
48 {
49 PipelineCacheHeaderVK a;
50 PipelineCacheHeaderVK b;
51 b.vendor_id = 100;
52 EXPECT_FALSE(a.IsCompatibleWith(b));
53 }
54 {
55 PipelineCacheHeaderVK a;
56 PipelineCacheHeaderVK b;
57 b.device_id = 100;
58 EXPECT_FALSE(a.IsCompatibleWith(b));
59 }
60 {
61 PipelineCacheHeaderVK a;
62 PipelineCacheHeaderVK b;
63 b.abi = a.abi / 2u;
64 EXPECT_FALSE(a.IsCompatibleWith(b));
65 }
66 {
67 PipelineCacheHeaderVK a;
68 PipelineCacheHeaderVK b;
69 for (size_t i = 0; i < VK_UUID_SIZE; i++) {
70 b.uuid[i] = a.uuid[i] + 1;
71 }
72 EXPECT_FALSE(a.IsCompatibleWith(b));
73 }
74 }

References impeller::PipelineCacheHeaderVK::abi, impeller::saturated::b, impeller::PipelineCacheHeaderVK::data_size, impeller::PipelineCacheHeaderVK::IsCompatibleWith(), and impeller::PipelineCacheHeaderVK::uuid.

## ◆ TEST() [229/389]

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() [230/389]

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() [231/389]

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() [232/389]

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

Definition at line 1302 of file rect_unittests.cc.

1302 {
1303 auto rect1 =
1304 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1305 auto rect2 = Rect::MakeXYWH(724.f, 618.f, 600.f, 300.f);
1306 EXPECT_TRUE(rect1.Contains(rect2));
1307 }

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

## ◆ TEST() [233/389]

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

Definition at line 885 of file rect_unittests.cc.

885 {
886 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
887
888 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
889 const std::string& label) {
890 EXPECT_FALSE(IRect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
891 << label << " with Top/Bottom swapped";
892 EXPECT_FALSE(IRect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
893 << label << " with Left/Right swapped";
894 EXPECT_FALSE(IRect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
895 << label << " with all sides swapped";
896 };
897
898 test(20, 20, 30, 30, "Above and Left");
899 test(70, 20, 80, 30, "Above");
900 test(120, 20, 130, 30, "Above and Right");
901 test(120, 70, 130, 80, "Right");
902 test(120, 120, 130, 130, "Below and Right");
903 test(70, 120, 80, 130, "Below");
904 test(20, 120, 30, 130, "Below and Left");
905 test(20, 70, 30, 80, "Left");
906
907 test(70, 70, 80, 80, "Inside");
908
909 test(40, 70, 60, 80, "Straddling Left");
910 test(70, 40, 80, 60, "Straddling Top");
911 test(90, 70, 110, 80, "Straddling Right");
912 test(70, 90, 80, 110, "Straddling Bottom");
913 }

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

## ◆ TEST() [234/389]

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

Definition at line 855 of file rect_unittests.cc.

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

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

## ◆ TEST() [235/389]

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

Definition at line 1225 of file rect_unittests.cc.

1225 {
1226 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1227 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1228 EXPECT_EQ(Rect::MakeMaximum().GetCenter(), Point(0, 0));
1229
1230 // Note that we expect a Point as the answer from an IRect
1231 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1232 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1233 EXPECT_EQ(IRect::MakeMaximum().GetCenter(), Point(0, 0));
1234 }

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

## ◆ TEST() [236/389]

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

Definition at line 1011 of file rect_unittests.cc.

1011 {
1012 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
1013 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
1014 EXPECT_EQ(IRect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
1015 EXPECT_EQ(IRect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
1016 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
1017 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
1018 }

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

## ◆ TEST() [237/389]

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

Definition at line 2398 of file rect_unittests.cc.

2398 {
2399 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2400 const std::string& label) {
2401 ASSERT_FALSE(rect.IsEmpty());
2402
2403 EXPECT_FALSE(flip_lr(rect).ContainsInclusive(point)) << label;
2404 EXPECT_FALSE(flip_tb(rect).ContainsInclusive(point)) << label;
2405 EXPECT_FALSE(flip_lrtb(rect).ContainsInclusive(point)) << label;
2406 };
2407
2408 auto test_inside = [&check_empty_flips](const IRect& rect,
2409 const IPoint& point) {
2410 ASSERT_FALSE(rect.IsEmpty()) << rect;
2411
2412 std::stringstream stream;
2413 stream << rect << " contains " << point;
2414 auto label = stream.str();
2415
2416 EXPECT_TRUE(rect.ContainsInclusive(point)) << label;
2417 check_empty_flips(rect, point, label);
2418 };
2419
2420 auto test_outside = [&check_empty_flips](const IRect& rect,
2421 const IPoint& point) {
2422 ASSERT_FALSE(rect.IsEmpty()) << rect;
2423
2424 std::stringstream stream;
2425 stream << rect << " contains " << point;
2426 auto label = stream.str();
2427
2428 EXPECT_FALSE(rect.ContainsInclusive(point)) << label;
2429 check_empty_flips(rect, point, label);
2430 };
2431
2432 {
2433 // Origin is inclusive
2434 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2435 auto p = IPoint(100, 100);
2436
2437 test_inside(r, p);
2438 }
2439 {
2440 // Size is inclusive
2441 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2442 auto p = IPoint(200, 200);
2443
2444 test_inside(r, p);
2445 }
2446 {
2447 // Size + "epsilon" is exclusive
2448 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2449 auto p = IPoint(201, 201);
2450
2451 test_outside(r, p);
2452 }
2453 {
2454 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2455 auto p = IPoint(99, 99);
2456
2457 test_outside(r, p);
2458 }
2459 {
2460 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2461 auto p = IPoint(199, 199);
2462
2463 test_inside(r, p);
2464 }
2465
2466 {
2467 auto r = IRect::MakeMaximum();
2468 auto p = IPoint(199, 199);
2469
2470 test_inside(r, p);
2471 }
2472 }

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() [238/389]

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

Definition at line 2236 of file rect_unittests.cc.

2236 {
2237 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2238 const std::string& label) {
2239 ASSERT_FALSE(rect.IsEmpty());
2240
2241 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2242 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2243 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2244 };
2245
2246 auto test_inside = [&check_empty_flips](const IRect& rect,
2247 const IPoint& point) {
2248 ASSERT_FALSE(rect.IsEmpty()) << rect;
2249
2250 std::stringstream stream;
2251 stream << rect << " contains " << point;
2252 auto label = stream.str();
2253
2254 EXPECT_TRUE(rect.Contains(point)) << label;
2255 check_empty_flips(rect, point, label);
2256 };
2257
2258 auto test_outside = [&check_empty_flips](const IRect& rect,
2259 const IPoint& point) {
2260 ASSERT_FALSE(rect.IsEmpty()) << rect;
2261
2262 std::stringstream stream;
2263 stream << rect << " contains " << point;
2264 auto label = stream.str();
2265
2266 EXPECT_FALSE(rect.Contains(point)) << label;
2267 check_empty_flips(rect, point, label);
2268 };
2269
2270 {
2271 // Origin is inclusive
2272 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2273 auto p = IPoint(100, 100);
2274
2275 test_inside(r, p);
2276 }
2277 {
2278 // Size is exclusive
2279 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2280 auto p = IPoint(200, 200);
2281
2282 test_outside(r, p);
2283 }
2284 {
2285 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2286 auto p = IPoint(99, 99);
2287
2288 test_outside(r, p);
2289 }
2290 {
2291 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2292 auto p = IPoint(199, 199);
2293
2294 test_inside(r, p);
2295 }
2296
2297 {
2298 auto r = IRect::MakeMaximum();
2299 auto p = IPoint(199, 199);
2300
2301 test_inside(r, p);
2302 }
2303 }

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() [239/389]

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

Definition at line 2589 of file rect_unittests.cc.

2589 {
2590 auto check_empty_flips = [](const IRect& a, const IRect& b,
2591 const std::string& label) {
2592 ASSERT_FALSE(a.IsEmpty());
2593 // test b rects are allowed to have 0 w/h, but not be backwards
2594 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2595
2596 // unflipped a vs flipped (empty) b yields true
2597 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2598 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2599 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2600
2601 // flipped (empty) a vs unflipped b yields false
2602 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2603 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2604 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2605
2606 // flipped (empty) a vs flipped (empty) b yields empty
2607 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2608 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2609 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2610 };
2611
2612 auto test_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2613 ASSERT_FALSE(a.IsEmpty()) << a;
2614 // test b rects are allowed to have 0 w/h, but not be backwards
2615 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2616
2617 std::stringstream stream;
2618 stream << a << " contains " << b;
2619 auto label = stream.str();
2620
2621 EXPECT_TRUE(a.Contains(b)) << label;
2622 check_empty_flips(a, b, label);
2623 };
2624
2625 auto test_not_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2626 ASSERT_FALSE(a.IsEmpty()) << a;
2627 // If b was empty, it would be contained and should not be tested with
2628 // this function - use |test_inside| instead.
2629 ASSERT_FALSE(b.IsEmpty()) << b;
2630
2631 std::stringstream stream;
2632 stream << a << " contains " << b;
2633 auto label = stream.str();
2634
2635 EXPECT_FALSE(a.Contains(b)) << label;
2636 check_empty_flips(a, b, label);
2637 };
2638
2639 {
2640 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2641
2642 test_inside(a, a);
2643 }
2644 {
2645 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2646 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2647
2648 test_inside(a, b);
2649 }
2650 {
2651 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2652 auto b = IRect::MakeXYWH(150, 150, 20, 20);
2653
2654 test_inside(a, b);
2655 }
2656 {
2657 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2658 auto b = IRect::MakeXYWH(150, 150, 100, 100);
2659
2660 test_not_inside(a, b);
2661 }
2662 {
2663 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2664 auto b = IRect::MakeXYWH(50, 50, 100, 100);
2665
2666 test_not_inside(a, b);
2667 }
2668 {
2669 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2670 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2671
2672 test_not_inside(a, b);
2673 }
2674 {
2675 auto a = IRect::MakeMaximum();
2676 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2677
2678 test_inside(a, b);
2679 }
2680 }

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() [240/389]

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

Definition at line 672 of file rect_unittests.cc.

672 {
673 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
674 IRect copy = rect;
675
676 EXPECT_EQ(rect, copy);
677 EXPECT_EQ(copy.GetLeft(), 5);
678 EXPECT_EQ(copy.GetTop(), 10);
679 EXPECT_EQ(copy.GetRight(), 20);
680 EXPECT_EQ(copy.GetBottom(), 25);
681 EXPECT_EQ(copy.GetX(), 5);
682 EXPECT_EQ(copy.GetY(), 10);
683 EXPECT_EQ(copy.GetWidth(), 15);
684 EXPECT_EQ(copy.GetHeight(), 15);
685 EXPECT_FALSE(copy.IsEmpty());
686 }

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() [241/389]

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

Definition at line 2834 of file rect_unittests.cc.

2834 {
2835 IRect cull_rect = IRect::MakeLTRB(20, 20, 40, 40);
2836
2837 auto check_empty_flips = [&cull_rect](const IRect& diff_rect,
2838 const std::string& label) {
2839 EXPECT_FALSE(diff_rect.IsEmpty());
2840 EXPECT_FALSE(cull_rect.IsEmpty());
2841
2842 // unflipped cull_rect vs flipped(empty) diff_rect
2843 // == cull_rect
2844 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2845 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2846 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2847 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2848 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2849 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2850
2851 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2852 // == empty
2853 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2854 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2855 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2856 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2857 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2858 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2859
2860 // flipped(empty) cull_rect vs unflipped diff_rect
2861 // == empty
2862 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2863 << label;
2864 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), IRect())
2865 << label;
2866 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2867 << label;
2868 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), IRect())
2869 << label;
2870 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2871 << label;
2872 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), IRect())
2873 << label;
2874 };
2875
2876 auto non_reducing = [&cull_rect, &check_empty_flips](
2877 const IRect& diff_rect, const std::string& label) {
2878 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2879 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2880 check_empty_flips(diff_rect, label);
2881 };
2882
2883 auto reducing = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2884 const IRect& result_rect,
2885 const std::string& label) {
2886 EXPECT_TRUE(!result_rect.IsEmpty());
2887 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2888 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2889 check_empty_flips(diff_rect, label);
2890 };
2891
2892 auto emptying = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2893 const std::string& label) {
2894 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2895 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), IRect()) << label;
2896 check_empty_flips(diff_rect, label);
2897 };
2898
2899 // Skim the corners and edge
2900 non_reducing(IRect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2901 non_reducing(IRect::MakeLTRB(20, 10, 40, 20), "Above");
2902 non_reducing(IRect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2903 non_reducing(IRect::MakeLTRB(40, 20, 50, 40), "Right");
2904 non_reducing(IRect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2905 non_reducing(IRect::MakeLTRB(20, 40, 40, 50), "Below");
2906 non_reducing(IRect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2907 non_reducing(IRect::MakeLTRB(10, 20, 20, 40), "Left");
2908
2909 // Overlap corners
2910 non_reducing(IRect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2911 non_reducing(IRect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2912 non_reducing(IRect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2913 non_reducing(IRect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2914
2915 // Overlap edges, but not across an entire side
2916 non_reducing(IRect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2917 non_reducing(IRect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2918 non_reducing(IRect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2919 non_reducing(IRect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2920 non_reducing(IRect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2921 non_reducing(IRect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2922 non_reducing(IRect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2923 non_reducing(IRect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2924
2925 // Slice all the way through the middle
2926 non_reducing(IRect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2927 non_reducing(IRect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2928
2929 // Slice off each edge
2930 reducing(IRect::MakeLTRB(20, 15, 40, 25), //
2931 IRect::MakeLTRB(20, 25, 40, 40), //
2932 "Slice off top");
2933 reducing(IRect::MakeLTRB(35, 20, 45, 40), //
2934 IRect::MakeLTRB(20, 20, 35, 40), //
2935 "Slice off right");
2936 reducing(IRect::MakeLTRB(20, 35, 40, 45), //
2937 IRect::MakeLTRB(20, 20, 40, 35), //
2938 "Slice off bottom");
2939 reducing(IRect::MakeLTRB(15, 20, 25, 40), //
2940 IRect::MakeLTRB(25, 20, 40, 40), //
2941 "Slice off left");
2942
2943 // cull rect contains diff rect
2944 non_reducing(IRect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2945
2946 // cull rect equals diff rect
2947 emptying(cull_rect, "Perfectly covering");
2948
2949 // diff rect contains cull rect
2950 emptying(IRect::MakeLTRB(15, 15, 45, 45), "Smothering");
2951 }

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() [242/389]

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() [243/389]

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

Definition at line 825 of file rect_unittests.cc.

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

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

## ◆ TEST() [244/389]

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() [245/389]

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

Definition at line 1269 of file rect_unittests.cc.

1269 {
1270 auto rect = IRect::MakeLTRB(100, 100, 200, 200);
1271
1272 // Expand(T amount)
1273 EXPECT_EQ(rect.Expand(10), IRect::MakeLTRB(90, 90, 210, 210));
1274 EXPECT_EQ(rect.Expand(-10), IRect::MakeLTRB(110, 110, 190, 190));
1275
1276 // Expand(amount, amount)
1277 EXPECT_EQ(rect.Expand(10, 10), IRect::MakeLTRB(90, 90, 210, 210));
1278 EXPECT_EQ(rect.Expand(10, -10), IRect::MakeLTRB(90, 110, 210, 190));
1279 EXPECT_EQ(rect.Expand(-10, 10), IRect::MakeLTRB(110, 90, 190, 210));
1280 EXPECT_EQ(rect.Expand(-10, -10), IRect::MakeLTRB(110, 110, 190, 190));
1281
1282 // Expand(amount, amount, amount, amount)
1283 EXPECT_EQ(rect.Expand(10, 20, 30, 40), IRect::MakeLTRB(90, 80, 230, 240));
1284 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), IRect::MakeLTRB(110, 80, 230, 240));
1285 EXPECT_EQ(rect.Expand(10, -20, 30, 40), IRect::MakeLTRB(90, 120, 230, 240));
1286 EXPECT_EQ(rect.Expand(10, 20, -30, 40), IRect::MakeLTRB(90, 80, 170, 240));
1287 EXPECT_EQ(rect.Expand(10, 20, 30, -40), IRect::MakeLTRB(90, 80, 230, 160));
1288
1289 // Expand(IPoint amount)
1290 EXPECT_EQ(rect.Expand(IPoint{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1291 EXPECT_EQ(rect.Expand(IPoint{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1292 EXPECT_EQ(rect.Expand(IPoint{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1293 EXPECT_EQ(rect.Expand(IPoint{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1294
1295 // Expand(ISize amount)
1296 EXPECT_EQ(rect.Expand(ISize{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1297 EXPECT_EQ(rect.Expand(ISize{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1298 EXPECT_EQ(rect.Expand(ISize{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1299 EXPECT_EQ(rect.Expand(ISize{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1300 }

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

## ◆ TEST() [246/389]

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

Definition at line 647 of file rect_unittests.cc.

647 {
648 EXPECT_EQ(IRect(IRect::MakeXYWH(2, 3, 7, 15)), //
649 IRect::MakeXYWH(2, 3, 7, 15));
650 EXPECT_EQ(IRect(IRect::MakeLTRB(2, 3, 7, 15)), //
651 IRect::MakeLTRB(2, 3, 7, 15));
652 }

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

## ◆ TEST() [247/389]

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

Definition at line 1108 of file rect_unittests.cc.

1108 {
1109 {
1110 // Checks for expected matrix values
1111
1112 auto r = IRect::MakeXYWH(100, 200, 200, 400);
1113
1114 EXPECT_EQ(r.GetNormalizingTransform(),
1115 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1116 Matrix::MakeTranslation({-100, -200}));
1117 }
1118
1119 {
1120 // Checks for expected transform of points relative to the rect
1121
1122 auto r = IRect::MakeLTRB(300, 500, 400, 700);
1123 auto m = r.GetNormalizingTransform();
1124
1125 // The 4 corners of the rect => (0, 0) to (1, 1)
1126 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1127 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1128 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1129 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1130
1131 // The center => (0.5, 0.5)
1132 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1133
1134 // Outside the 4 corners => (-1, -1) to (2, 2)
1135 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1136 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1137 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1138 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1139 }
1140
1141 {
1142 // Checks for behavior with empty rects
1143
1144 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1145
1146 // Empty for width and/or height == 0
1147 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1148 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1149 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1150
1151 // Empty for width and/or height < 0
1152 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1153 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1154 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1155 }
1156 }

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

## ◆ TEST() [248/389]

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

Definition at line 1794 of file rect_unittests.cc.

1794 {
1795 auto check_empty_flips = [](const IRect& a, const IRect& b,
1796 const std::string& label) {
1797 ASSERT_FALSE(a.IsEmpty());
1798 // b is allowed to be empty
1799
1800 // unflipped a vs flipped (empty) b yields a
1801 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1802 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1803 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1804
1805 // flipped (empty) a vs unflipped b yields b
1806 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1807 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1808 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1809
1810 // flipped (empty) a vs flipped (empty) b yields empty
1811 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1812 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1813 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1814 };
1815
1816 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b,
1817 const IRect& result) {
1818 ASSERT_FALSE(a.IsEmpty()) << a;
1819 // b is allowed to be empty
1820
1821 std::stringstream stream;
1822 stream << a << " union " << b;
1823 auto label = stream.str();
1824
1825 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1826 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1827 EXPECT_EQ(a.Intersection(b), result) << label;
1828 EXPECT_EQ(b.Intersection(a), result) << label;
1829 check_empty_flips(a, b, label);
1830 };
1831
1832 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
1833 ASSERT_FALSE(a.IsEmpty()) << a;
1834 // b is allowed to be empty
1835
1836 std::stringstream stream;
1837 stream << a << " union " << b;
1838 auto label = stream.str();
1839
1840 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1841 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1842 check_empty_flips(a, b, label);
1843 };
1844
1845 {
1846 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1847 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1848
1849 test_empty(a, b);
1850 }
1851
1852 {
1853 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1854 auto b = IRect::MakeXYWH(10, 10, 0, 0);
1855
1856 test_empty(a, b);
1857 }
1858
1859 {
1860 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1861 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1862 auto expected = IRect::MakeXYWH(10, 10, 90, 90);
1863
1864 test_non_empty(a, b, expected);
1865 }
1866
1867 {
1868 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1869 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1870
1871 test_empty(a, b);
1872 }
1873
1874 {
1875 auto a = IRect::MakeMaximum();
1876 auto b = IRect::MakeXYWH(10, 10, 300, 300);
1877
1878 test_non_empty(a, b, b);
1879 }
1880
1881 {
1882 auto a = IRect::MakeMaximum();
1883 auto b = IRect::MakeMaximum();
1884
1885 test_non_empty(a, b, IRect::MakeMaximum());
1886 }
1887 }

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() [249/389]

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

Definition at line 2059 of file rect_unittests.cc.

2059 {
2060 auto check_empty_flips = [](const IRect& a, const IRect& b,
2061 const std::string& label) {
2062 ASSERT_FALSE(a.IsEmpty());
2063 // b is allowed to be empty
2064
2065 // unflipped a vs flipped (empty) b yields a
2066 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
2067 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
2068 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
2069
2070 // flipped (empty) a vs unflipped b yields b
2071 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
2072 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
2073 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
2074
2075 // flipped (empty) a vs flipped (empty) b yields empty
2076 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
2077 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
2078 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
2079 };
2080
2081 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2082 ASSERT_FALSE(a.IsEmpty()) << a;
2083 // b is allowed to be empty
2084
2085 std::stringstream stream;
2086 stream << a << " union " << b;
2087 auto label = stream.str();
2088
2089 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
2090 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
2091 check_empty_flips(a, b, label);
2092 };
2093
2094 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2095 ASSERT_FALSE(a.IsEmpty()) << a;
2096 // b is allowed to be empty
2097
2098 std::stringstream stream;
2099 stream << a << " union " << b;
2100 auto label = stream.str();
2101
2102 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
2103 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
2104 check_empty_flips(a, b, label);
2105 };
2106
2107 {
2108 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2109 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2110
2111 test_empty(a, b);
2112 }
2113
2114 {
2115 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2116 auto b = IRect::MakeXYWH(10, 10, 0, 0);
2117
2118 test_empty(a, b);
2119 }
2120
2121 {
2122 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2123 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2124
2125 test_non_empty(a, b);
2126 }
2127
2128 {
2129 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2130 auto b = IRect::MakeXYWH(100, 100, 100, 100);
2131
2132 test_empty(a, b);
2133 }
2134
2135 {
2136 auto a = IRect::MakeMaximum();
2137 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2138
2139 test_non_empty(a, b);
2140 }
2141
2142 {
2143 auto a = IRect::MakeMaximum();
2144 auto b = IRect::MakeMaximum();
2145
2146 test_non_empty(a, b);
2147 }
2148 }

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() [250/389]

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

Definition at line 624 of file rect_unittests.cc.

624 {
625 IRect rect = IRect::MakeMaximum();
626 auto min = std::numeric_limits<int64_t>::min();
627 auto max = std::numeric_limits<int64_t>::max();
628
629 EXPECT_EQ(rect.GetLeft(), min);
630 EXPECT_EQ(rect.GetTop(), min);
631 EXPECT_EQ(rect.GetRight(), max);
632 EXPECT_EQ(rect.GetBottom(), max);
633 EXPECT_EQ(rect.GetX(), min);
634 EXPECT_EQ(rect.GetY(), min);
635 EXPECT_EQ(rect.GetWidth(), max);
636 EXPECT_EQ(rect.GetHeight(), max);
637 EXPECT_FALSE(rect.IsEmpty());
638 }

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() [251/389]

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

Definition at line 714 of file rect_unittests.cc.

714 {
715 {
716 IRect r = IRect::MakeOriginSize({10, 20}, {50, 40});
717 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
718 EXPECT_EQ(r.GetSize(), ISize(50, 40));
719 EXPECT_EQ(r.GetX(), 10);
720 EXPECT_EQ(r.GetY(), 20);
721 EXPECT_EQ(r.GetWidth(), 50);
722 EXPECT_EQ(r.GetHeight(), 40);
723 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
724 EXPECT_EQ(r.GetXYWH(), expected_array);
725 }
726
727 {
728 IRect r = IRect::MakeLTRB(10, 20, 50, 40);
729 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
730 EXPECT_EQ(r.GetSize(), ISize(40, 20));
731 EXPECT_EQ(r.GetX(), 10);
732 EXPECT_EQ(r.GetY(), 20);
733 EXPECT_EQ(r.GetWidth(), 40);
734 EXPECT_EQ(r.GetHeight(), 20);
735 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
736 EXPECT_EQ(r.GetXYWH(), expected_array);
737 }
738 }

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() [252/389]

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

Definition at line 509 of file rect_unittests.cc.

509 {
510 auto min = std::numeric_limits<int64_t>::min();
511 auto max = std::numeric_limits<int64_t>::max();
512
513 // 4 cases
514 // negative l, r near max takes width past max
515 // positive l, r near min takes width below min
516 // negative t, b near max takes width past max
517 // positive t, b near min takes width below min
518
519 {
520 IRect rect = IRect::MakeLTRB(-10, 10, max - 5, 26);
521
522 EXPECT_EQ(rect.GetLeft(), -10);
523 EXPECT_EQ(rect.GetTop(), 10);
524 EXPECT_EQ(rect.GetRight(), max - 5);
525 EXPECT_EQ(rect.GetBottom(), 26);
526 EXPECT_EQ(rect.GetX(), -10);
527 EXPECT_EQ(rect.GetY(), 10);
528 EXPECT_EQ(rect.GetWidth(), max);
529 EXPECT_EQ(rect.GetHeight(), 16);
530 EXPECT_FALSE(rect.IsEmpty());
531 }
532
533 {
534 IRect rect = IRect::MakeLTRB(10, 10, min + 5, 26);
535
536 EXPECT_EQ(rect.GetLeft(), 10);
537 EXPECT_EQ(rect.GetTop(), 10);
538 EXPECT_EQ(rect.GetRight(), min + 5);
539 EXPECT_EQ(rect.GetBottom(), 26);
540 EXPECT_EQ(rect.GetX(), 10);
541 EXPECT_EQ(rect.GetY(), 10);
542 EXPECT_EQ(rect.GetWidth(), min);
543 EXPECT_EQ(rect.GetHeight(), 16);
544 EXPECT_TRUE(rect.IsEmpty());
545 }
546
547 {
548 IRect rect = IRect::MakeLTRB(5, -10, 15, max - 5);
549
550 EXPECT_EQ(rect.GetLeft(), 5);
551 EXPECT_EQ(rect.GetTop(), -10);
552 EXPECT_EQ(rect.GetRight(), 15);
553 EXPECT_EQ(rect.GetBottom(), max - 5);
554 EXPECT_EQ(rect.GetX(), 5);
555 EXPECT_EQ(rect.GetY(), -10);
556 EXPECT_EQ(rect.GetWidth(), 10);
557 EXPECT_EQ(rect.GetHeight(), max);
558 EXPECT_FALSE(rect.IsEmpty());
559 }
560
561 {
562 IRect rect = IRect::MakeLTRB(5, 10, 15, min + 5);
563
564 EXPECT_EQ(rect.GetLeft(), 5);
565 EXPECT_EQ(rect.GetTop(), 10);
566 EXPECT_EQ(rect.GetRight(), 15);
567 EXPECT_EQ(rect.GetBottom(), min + 5);
568 EXPECT_EQ(rect.GetX(), 5);
569 EXPECT_EQ(rect.GetY(), 10);
570 EXPECT_EQ(rect.GetWidth(), 10);
571 EXPECT_EQ(rect.GetHeight(), min);
572 EXPECT_TRUE(rect.IsEmpty());
573 }
574 }

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() [253/389]

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

Definition at line 303 of file rect_unittests.cc.

303 {
304 auto min = std::numeric_limits<int64_t>::min();
305 auto max = std::numeric_limits<int64_t>::max();
306
307 // 4 cases
308 // x near max, positive w takes it past max
309 // x near min, negative w takes it below min
310 // y near max, positive h takes it past max
311 // y near min, negative h takes it below min
312
313 {
314 IRect rect = IRect::MakeXYWH(max - 5, 10, 10, 16);
315
316 EXPECT_EQ(rect.GetLeft(), max - 5);
317 EXPECT_EQ(rect.GetTop(), 10);
318 EXPECT_EQ(rect.GetRight(), max);
319 EXPECT_EQ(rect.GetBottom(), 26);
320 EXPECT_EQ(rect.GetX(), max - 5);
321 EXPECT_EQ(rect.GetY(), 10);
322 EXPECT_EQ(rect.GetWidth(), 5);
323 EXPECT_EQ(rect.GetHeight(), 16);
324 EXPECT_FALSE(rect.IsEmpty());
325 }
326
327 {
328 IRect rect = IRect::MakeXYWH(min + 5, 10, -10, 16);
329
330 EXPECT_EQ(rect.GetLeft(), min + 5);
331 EXPECT_EQ(rect.GetTop(), 10);
332 EXPECT_EQ(rect.GetRight(), min);
333 EXPECT_EQ(rect.GetBottom(), 26);
334 EXPECT_EQ(rect.GetX(), min + 5);
335 EXPECT_EQ(rect.GetY(), 10);
336 EXPECT_EQ(rect.GetWidth(), -5);
337 EXPECT_EQ(rect.GetHeight(), 16);
338 EXPECT_TRUE(rect.IsEmpty());
339 }
340
341 {
342 IRect rect = IRect::MakeXYWH(5, max - 10, 10, 16);
343
344 EXPECT_EQ(rect.GetLeft(), 5);
345 EXPECT_EQ(rect.GetTop(), max - 10);
346 EXPECT_EQ(rect.GetRight(), 15);
347 EXPECT_EQ(rect.GetBottom(), max);
348 EXPECT_EQ(rect.GetX(), 5);
349 EXPECT_EQ(rect.GetY(), max - 10);
350 EXPECT_EQ(rect.GetWidth(), 10);
351 EXPECT_EQ(rect.GetHeight(), 10);
352 EXPECT_FALSE(rect.IsEmpty());
353 }
354
355 {
356 IRect rect = IRect::MakeXYWH(5, min + 10, 10, -16);
357
358 EXPECT_EQ(rect.GetLeft(), 5);
359 EXPECT_EQ(rect.GetTop(), min + 10);
360 EXPECT_EQ(rect.GetRight(), 15);
361 EXPECT_EQ(rect.GetBottom(), min);
362 EXPECT_EQ(rect.GetX(), 5);
363 EXPECT_EQ(rect.GetY(), min + 10);
364 EXPECT_EQ(rect.GetWidth(), 10);
365 EXPECT_EQ(rect.GetHeight(), -10);
366 EXPECT_TRUE(rect.IsEmpty());
367 }
368 }

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() [254/389]

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

Definition at line 3092 of file rect_unittests.cc.

3092 {
3093 {
3094 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3095 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3096 EXPECT_EQ(IRect::Round(r), ir);
3097 }
3098 {
3099 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3100 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3101 EXPECT_EQ(IRect::Round(r), ir);
3102 }
3103 {
3104 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3105 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3106 EXPECT_EQ(IRect::Round(r), ir);
3107 }
3108 }

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

## ◆ TEST() [255/389]

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

Definition at line 3064 of file rect_unittests.cc.

3064 {
3065 {
3066 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3067 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3068 EXPECT_EQ(IRect::RoundOut(r), ir);
3069 }
3070 {
3071 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3072 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3073 EXPECT_EQ(IRect::RoundOut(r), ir);
3074 }
3075 }

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

## ◆ TEST() [256/389]

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

Definition at line 960 of file rect_unittests.cc.

960 {
961 auto test1 = [](IRect rect, int64_t scale) {
962 IRect expected = IRect::MakeXYWH(rect.GetX() * scale, //
963 rect.GetY() * scale, //
964 rect.GetWidth() * scale, //
965 rect.GetHeight() * scale);
966
967 EXPECT_EQ(rect.Scale(scale), expected) //
968 << rect << " * " << scale;
969 EXPECT_EQ(rect.Scale(scale, scale), expected) //
970 << rect << " * " << scale;
971 EXPECT_EQ(rect.Scale(IPoint(scale, scale)), expected) //
972 << rect << " * " << scale;
973 EXPECT_EQ(rect.Scale(ISize(scale, scale)), expected) //
974 << rect << " * " << scale;
975 };
976
977 auto test2 = [&test1](IRect rect, int64_t scale_x, int64_t scale_y) {
978 IRect expected = IRect::MakeXYWH(rect.GetX() * scale_x, //
979 rect.GetY() * scale_y, //
980 rect.GetWidth() * scale_x, //
981 rect.GetHeight() * scale_y);
982
983 EXPECT_EQ(rect.Scale(scale_x, scale_y), expected) //
984 << rect << " * " << scale_x << ", " << scale_y;
985 EXPECT_EQ(rect.Scale(IPoint(scale_x, scale_y)), expected) //
986 << rect << " * " << scale_x << ", " << scale_y;
987 EXPECT_EQ(rect.Scale(ISize(scale_x, scale_y)), expected) //
988 << rect << " * " << scale_x << ", " << scale_y;
989
990 test1(rect, scale_x);
991 test1(rect, scale_y);
992 };
993
994 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, 3);
995 test2(IRect::MakeLTRB(10, 15, 100, 150), 3, 2);
996 test2(IRect::MakeLTRB(10, 15, -100, 150), 2, 3);
997 test2(IRect::MakeLTRB(10, 15, 100, -150), 2, 3);
998 test2(IRect::MakeLTRB(10, 15, 100, 150), -2, 3);
999 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, -3);
1000 }

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() [257/389]

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() [258/389]

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

Definition at line 149 of file rect_unittests.cc.

149 {
150 // Using fractional-power-of-2 friendly values for equality tests
151 IRect rect = IRect::MakeWH(15, 25);
152
153 EXPECT_EQ(rect.GetLeft(), 0);
154 EXPECT_EQ(rect.GetTop(), 0);
155 EXPECT_EQ(rect.GetRight(), 15);
156 EXPECT_EQ(rect.GetBottom(), 25);
157 EXPECT_EQ(rect.GetX(), 0);
158 EXPECT_EQ(rect.GetY(), 0);
159 EXPECT_EQ(rect.GetWidth(), 15);
160 EXPECT_EQ(rect.GetHeight(), 25);
161 EXPECT_FALSE(rect.IsEmpty());
162 }

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

## ◆ TEST() [259/389]

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() [260/389]

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

Definition at line 1487 of file rect_unittests.cc.

1487 {
1488 auto check_empty_flips = [](const IRect& a, const IRect& b,
1489 const std::string& label) {
1490 ASSERT_FALSE(a.IsEmpty());
1491 // b is allowed to be empty
1492
1493 // unflipped a vs flipped (empty) b yields a
1494 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1495 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1496 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1497
1498 // flipped (empty) a vs unflipped b yields b
1499 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1500 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1501 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1502
1503 // flipped (empty) a vs flipped (empty) b yields empty
1504 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1505 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1506 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1507 };
1508
1509 auto test = [&check_empty_flips](const IRect& a, const IRect& b,
1510 const IRect& result) {
1511 ASSERT_FALSE(a.IsEmpty()) << a;
1512 // b is allowed to be empty
1513
1514 std::stringstream stream;
1515 stream << a << " union " << b;
1516 auto label = stream.str();
1517
1518 EXPECT_EQ(a.Union(b), result) << label;
1519 EXPECT_EQ(b.Union(a), result) << label;
1520 check_empty_flips(a, b, label);
1521 };
1522
1523 {
1524 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1525 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1526 auto expected = IRect::MakeXYWH(100, 100, 100, 100);
1527 test(a, b, expected);
1528 }
1529
1530 {
1531 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1532 auto b = IRect::MakeXYWH(0, 0, 1, 1);
1533 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1534 test(a, b, expected);
1535 }
1536
1537 {
1538 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1539 auto b = IRect::MakeXYWH(10, 10, 1, 1);
1540 auto expected = IRect::MakeXYWH(10, 10, 190, 190);
1541 test(a, b, expected);
1542 }
1543
1544 {
1545 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1546 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1547 auto expected = IRect::MakeXYWH(0, 0, 110, 110);
1548 test(a, b, expected);
1549 }
1550
1551 {
1552 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1553 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1554 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1555 test(a, b, expected);
1556 }
1557 }

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

## ◆ TEST() [261/389]

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

Definition at line 1182 of file rect_unittests.cc.

1182 {
1183 // Non-empty
1184 EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
1185
1186 // Empty both width and height both 0 or negative, in all combinations
1187 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
1188 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
1189 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
1190 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
1191
1192 // Empty for 0 or negative width or height (but not both at the same time)
1193 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
1194 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
1195 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
1196 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
1197 }

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

## ◆ TEST() [262/389]

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

Definition at line 1213 of file rect_unittests.cc.

1213 {
1214 EXPECT_TRUE(Rect::MakeXYWH(10, 30, 20, 20).IsSquare());
1215 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 20, 19).IsSquare());
1216 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 19, 20).IsSquare());
1217 EXPECT_TRUE(Rect::MakeMaximum().IsSquare());
1218
1219 EXPECT_TRUE(IRect::MakeXYWH(10, 30, 20, 20).IsSquare());
1220 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 20, 19).IsSquare());
1221 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 19, 20).IsSquare());
1222 EXPECT_TRUE(IRect::MakeMaximum().IsSquare());
1223 }

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

## ◆ TEST() [263/389]

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

Definition at line 1199 of file rect_unittests.cc.

1199 {
1200 Quad quad = {
1201 Point(10, 10),
1202 Point(20, 10),
1203 Point(10, 20),
1204 Point(20, 20),
1205 };
1206 std::optional<Rect> bounds = Rect::MakePointBounds(quad);
1207 EXPECT_TRUE(bounds.has_value());
1208 if (bounds.has_value()) {
1209 EXPECT_TRUE(RectNear(bounds.value(), Rect::MakeLTRB(10, 10, 20, 20)));
1210 }
1211 }

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

## ◆ TEST() [264/389]

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

Definition at line 1889 of file rect_unittests.cc.

1889 {
1890 auto a = IRect::MakeLTRB(0, 0, 110, 110);
1891 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1892 auto c = IRect::MakeLTRB(100, 0, 200, 110);
1893
1894 // NullOpt, NullOpt
1895 EXPECT_FALSE(IRect::Intersection(std::nullopt, std::nullopt).has_value());
1896 EXPECT_EQ(IRect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1897
1898 auto test1 = [](const IRect& r) {
1899 // Rect, NullOpt
1900 EXPECT_TRUE(IRect::Intersection(r, std::nullopt).has_value());
1901 EXPECT_EQ(IRect::Intersection(r, std::nullopt).value(), r);
1902
1903 // OptRect, NullOpt
1904 EXPECT_TRUE(
1905 IRect::Intersection(std::optional(r), std::nullopt).has_value());
1906 EXPECT_EQ(IRect::Intersection(std::optional(r), std::nullopt).value(), r);
1907
1908 // NullOpt, Rect
1909 EXPECT_TRUE(IRect::Intersection(std::nullopt, r).has_value());
1910 EXPECT_EQ(IRect::Intersection(std::nullopt, r).value(), r);
1911
1912 // NullOpt, OptRect
1913 EXPECT_TRUE(
1914 IRect::Intersection(std::nullopt, std::optional(r)).has_value());
1915 EXPECT_EQ(IRect::Intersection(std::nullopt, std::optional(r)).value(), r);
1916 };
1917
1918 test1(a);
1919 test1(b);
1920 test1(c);
1921
1922 auto test2 = [](const IRect& a, const IRect& b, const IRect& i) {
1923 ASSERT_EQ(a.Intersection(b), i);
1924
1925 // Rect, OptRect
1926 EXPECT_TRUE(IRect::Intersection(a, std::optional(b)).has_value());
1927 EXPECT_EQ(IRect::Intersection(a, std::optional(b)).value(), i);
1928
1929 // OptRect, Rect
1930 EXPECT_TRUE(IRect::Intersection(std::optional(a), b).has_value());
1931 EXPECT_EQ(IRect::Intersection(std::optional(a), b).value(), i);
1932
1933 // OptRect, OptRect
1934 EXPECT_TRUE(
1935 IRect::Intersection(std::optional(a), std::optional(b)).has_value());
1936 EXPECT_EQ(IRect::Intersection(std::optional(a), std::optional(b)).value(),
1937 i);
1938 };
1939
1940 test2(a, b, IRect::MakeLTRB(100, 100, 110, 110));
1941 test2(a, c, IRect::MakeLTRB(100, 0, 110, 110));
1942 test2(b, c, IRect::MakeLTRB(100, 100, 200, 110));
1943 }

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

## ◆ TEST() [265/389]

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

Definition at line 1559 of file rect_unittests.cc.

1559 {
1560 auto a = IRect::MakeLTRB(0, 0, 100, 100);
1561 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1562 auto c = IRect::MakeLTRB(100, 0, 200, 100);
1563
1564 // NullOpt, NullOpt
1565 EXPECT_FALSE(IRect::Union(std::nullopt, std::nullopt).has_value());
1566 EXPECT_EQ(IRect::Union(std::nullopt, std::nullopt), std::nullopt);
1567
1568 auto test1 = [](const IRect& r) {
1569 // Rect, NullOpt
1570 EXPECT_TRUE(IRect::Union(r, std::nullopt).has_value());
1571 EXPECT_EQ(IRect::Union(r, std::nullopt).value(), r);
1572
1573 // OptRect, NullOpt
1574 EXPECT_TRUE(IRect::Union(std::optional(r), std::nullopt).has_value());
1575 EXPECT_EQ(IRect::Union(std::optional(r), std::nullopt).value(), r);
1576
1577 // NullOpt, Rect
1578 EXPECT_TRUE(IRect::Union(std::nullopt, r).has_value());
1579 EXPECT_EQ(IRect::Union(std::nullopt, r).value(), r);
1580
1581 // NullOpt, OptRect
1582 EXPECT_TRUE(IRect::Union(std::nullopt, std::optional(r)).has_value());
1583 EXPECT_EQ(IRect::Union(std::nullopt, std::optional(r)).value(), r);
1584 };
1585
1586 test1(a);
1587 test1(b);
1588 test1(c);
1589
1590 auto test2 = [](const IRect& a, const IRect& b, const IRect& u) {
1591 ASSERT_EQ(a.Union(b), u);
1592
1593 // Rect, OptRect
1594 EXPECT_TRUE(IRect::Union(a, std::optional(b)).has_value());
1595 EXPECT_EQ(IRect::Union(a, std::optional(b)).value(), u);
1596
1597 // OptRect, Rect
1598 EXPECT_TRUE(IRect::Union(std::optional(a), b).has_value());
1599 EXPECT_EQ(IRect::Union(std::optional(a), b).value(), u);
1600
1601 // OptRect, OptRect
1602 EXPECT_TRUE(IRect::Union(std::optional(a), std::optional(b)).has_value());
1603 EXPECT_EQ(IRect::Union(std::optional(a), std::optional(b)).value(), u);
1604 };
1605
1606 test2(a, b, IRect::MakeLTRB(0, 0, 200, 200));
1607 test2(a, c, IRect::MakeLTRB(0, 0, 200, 100));
1608 test2(b, c, IRect::MakeLTRB(100, 0, 200, 200));
1609 }

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

## ◆ TEST() [266/389]

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

Definition at line 1740 of file rect_unittests.cc.

1740 {
1741 auto a = Rect::MakeLTRB(0, 0, 110, 110);
1742 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1743 auto c = Rect::MakeLTRB(100, 0, 200, 110);
1744
1745 // NullOpt, NullOpt
1746 EXPECT_FALSE(Rect::Intersection(std::nullopt, std::nullopt).has_value());
1747 EXPECT_EQ(Rect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1748
1749 auto test1 = [](const Rect& r) {
1750 // Rect, NullOpt
1751 EXPECT_TRUE(Rect::Intersection(r, std::nullopt).has_value());
1752 EXPECT_EQ(Rect::Intersection(r, std::nullopt).value(), r);
1753
1754 // OptRect, NullOpt
1755 EXPECT_TRUE(Rect::Intersection(std::optional(r), std::nullopt).has_value());
1756 EXPECT_EQ(Rect::Intersection(std::optional(r), std::nullopt).value(), r);
1757
1758 // NullOpt, Rect
1759 EXPECT_TRUE(Rect::Intersection(std::nullopt, r).has_value());
1760 EXPECT_EQ(Rect::Intersection(std::nullopt, r).value(), r);
1761
1762 // NullOpt, OptRect
1763 EXPECT_TRUE(Rect::Intersection(std::nullopt, std::optional(r)).has_value());
1764 EXPECT_EQ(Rect::Intersection(std::nullopt, std::optional(r)).value(), r);
1765 };
1766
1767 test1(a);
1768 test1(b);
1769 test1(c);
1770
1771 auto test2 = [](const Rect& a, const Rect& b, const Rect& i) {
1772 ASSERT_EQ(a.Intersection(b), i);
1773
1774 // Rect, OptRect
1775 EXPECT_TRUE(Rect::Intersection(a, std::optional(b)).has_value());
1776 EXPECT_EQ(Rect::Intersection(a, std::optional(b)).value(), i);
1777
1778 // OptRect, Rect
1779 EXPECT_TRUE(Rect::Intersection(std::optional(a), b).has_value());
1780 EXPECT_EQ(Rect::Intersection(std::optional(a), b).value(), i);
1781
1782 // OptRect, OptRect
1783 EXPECT_TRUE(
1784 Rect::Intersection(std::optional(a), std::optional(b)).has_value());
1785 EXPECT_EQ(Rect::Intersection(std::optional(a), std::optional(b)).value(),
1786 i);
1787 };
1788
1789 test2(a, b, Rect::MakeLTRB(100, 100, 110, 110));
1790 test2(a, c, Rect::MakeLTRB(100, 0, 110, 110));
1791 test2(b, c, Rect::MakeLTRB(100, 100, 200, 110));
1792 }

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

## ◆ TEST() [267/389]

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

Definition at line 1435 of file rect_unittests.cc.

1435 {
1436 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1437 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1438 auto c = Rect::MakeLTRB(100, 0, 200, 100);
1439
1440 // NullOpt, NullOpt
1441 EXPECT_FALSE(Rect::Union(std::nullopt, std::nullopt).has_value());
1442 EXPECT_EQ(Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1443
1444 auto test1 = [](const Rect& r) {
1445 // Rect, NullOpt
1446 EXPECT_TRUE(Rect::Union(r, std::nullopt).has_value());
1447 EXPECT_EQ(Rect::Union(r, std::nullopt).value(), r);
1448
1449 // OptRect, NullOpt
1450 EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
1451 EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
1452
1453 // NullOpt, Rect
1454 EXPECT_TRUE(Rect::Union(std::nullopt, r).has_value());
1455 EXPECT_EQ(Rect::Union(std::nullopt, r).value(), r);
1456
1457 // NullOpt, OptRect
1458 EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
1459 EXPECT_EQ(Rect::Union(std::nullopt, std::optional(r)).value(), r);
1460 };
1461
1462 test1(a);
1463 test1(b);
1464 test1(c);
1465
1466 auto test2 = [](const Rect& a, const Rect& b, const Rect& u) {
1467 ASSERT_EQ(a.Union(b), u);
1468
1469 // Rect, OptRect
1470 EXPECT_TRUE(Rect::Union(a, std::optional(b)).has_value());
1471 EXPECT_EQ(Rect::Union(a, std::optional(b)).value(), u);
1472
1473 // OptRect, Rect
1474 EXPECT_TRUE(Rect::Union(std::optional(a), b).has_value());
1475 EXPECT_EQ(Rect::Union(std::optional(a), b).value(), u);
1476
1477 // OptRect, OptRect
1478 EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
1479 EXPECT_EQ(Rect::Union(std::optional(a), std::optional(b)).value(), u);
1480 };
1481
1482 test2(a, b, Rect::MakeLTRB(0, 0, 200, 200));
1483 test2(a, c, Rect::MakeLTRB(0, 0, 200, 100));
1484 test2(b, c, Rect::MakeLTRB(100, 0, 200, 200));
1485 }

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

## ◆ TEST() [268/389]

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

Definition at line 1002 of file rect_unittests.cc.

1002 {
1003 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
1004 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
1005 EXPECT_EQ(Rect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
1006 EXPECT_EQ(Rect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
1007 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
1008 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
1009 }

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

## ◆ TEST() [269/389]

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

Definition at line 2305 of file rect_unittests.cc.

2305 {
2306 auto check_nans = [](const Rect& rect, const Point& point,
2307 const std::string& label) {
2308 ASSERT_TRUE(rect.IsFinite()) << label;
2309 ASSERT_TRUE(point.IsFinite()) << label;
2310
2311 for (int i = 1; i < 16; i++) {
2312 EXPECT_FALSE(swap_nan(rect, i).ContainsInclusive(point))
2313 << label << ", index = " << i;
2314 for (int j = 1; j < 4; j++) {
2315 EXPECT_FALSE(swap_nan(rect, i).ContainsInclusive(swap_nan(point, j)))
2316 << label << ", indices = " << i << ", " << j;
2317 }
2318 }
2319 };
2320
2321 auto check_empty_flips = [](const Rect& rect, const Point& point,
2322 const std::string& label) {
2323 ASSERT_FALSE(rect.IsEmpty());
2324
2325 EXPECT_FALSE(flip_lr(rect).ContainsInclusive(point)) << label;
2326 EXPECT_FALSE(flip_tb(rect).ContainsInclusive(point)) << label;
2327 EXPECT_FALSE(flip_lrtb(rect).ContainsInclusive(point)) << label;
2328 };
2329
2330 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2331 const Point& point) {
2332 ASSERT_FALSE(rect.IsEmpty()) << rect;
2333
2334 std::stringstream stream;
2335 stream << rect << " contains " << point;
2336 auto label = stream.str();
2337
2338 EXPECT_TRUE(rect.ContainsInclusive(point)) << label;
2339 check_empty_flips(rect, point, label);
2340 check_nans(rect, point, label);
2341 };
2342
2343 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2344 const Point& point) {
2345 ASSERT_FALSE(rect.IsEmpty()) << rect;
2346
2347 std::stringstream stream;
2348 stream << rect << " contains " << point;
2349 auto label = stream.str();
2350
2351 EXPECT_FALSE(rect.ContainsInclusive(point)) << label;
2352 check_empty_flips(rect, point, label);
2353 check_nans(rect, point, label);
2354 };
2355
2356 {
2357 // Origin is inclusive
2358 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2359 auto p = Point(100, 100);
2360
2361 test_inside(r, p);
2362 }
2363 {
2364 // Size is inclusive
2365 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2366 auto p = Point(200, 200);
2367
2368 test_inside(r, p);
2369 }
2370 {
2371 // Size + epsilon is exclusive
2372 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2373 auto p = Point(200 + kEhCloseEnough, 200 + kEhCloseEnough);
2374
2375 test_outside(r, p);
2376 }
2377 {
2378 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2379 auto p = Point(99, 99);
2380
2381 test_outside(r, p);
2382 }
2383 {
2384 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2385 auto p = Point(199, 199);
2386
2387 test_inside(r, p);
2388 }
2389
2390 {
2391 auto r = Rect::MakeMaximum();
2392 auto p = Point(199, 199);
2393
2394 test_inside(r, p);
2395 }
2396 }

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() [270/389]

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

Definition at line 2150 of file rect_unittests.cc.

2150 {
2151 auto check_nans = [](const Rect& rect, const Point& point,
2152 const std::string& label) {
2153 ASSERT_TRUE(rect.IsFinite()) << label;
2154 ASSERT_TRUE(point.IsFinite()) << label;
2155
2156 for (int i = 1; i < 16; i++) {
2157 EXPECT_FALSE(swap_nan(rect, i).Contains(point))
2158 << label << ", index = " << i;
2159 for (int j = 1; j < 4; j++) {
2160 EXPECT_FALSE(swap_nan(rect, i).Contains(swap_nan(point, j)))
2161 << label << ", indices = " << i << ", " << j;
2162 }
2163 }
2164 };
2165
2166 auto check_empty_flips = [](const Rect& rect, const Point& point,
2167 const std::string& label) {
2168 ASSERT_FALSE(rect.IsEmpty());
2169
2170 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2171 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2172 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2173 };
2174
2175 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2176 const Point& point) {
2177 ASSERT_FALSE(rect.IsEmpty()) << rect;
2178
2179 std::stringstream stream;
2180 stream << rect << " contains " << point;
2181 auto label = stream.str();
2182
2183 EXPECT_TRUE(rect.Contains(point)) << label;
2184 check_empty_flips(rect, point, label);
2185 check_nans(rect, point, label);
2186 };
2187
2188 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2189 const Point& point) {
2190 ASSERT_FALSE(rect.IsEmpty()) << rect;
2191
2192 std::stringstream stream;
2193 stream << rect << " contains " << point;
2194 auto label = stream.str();
2195
2196 EXPECT_FALSE(rect.Contains(point)) << label;
2197 check_empty_flips(rect, point, label);
2198 check_nans(rect, point, label);
2199 };
2200
2201 {
2202 // Origin is inclusive
2203 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2204 auto p = Point(100, 100);
2205
2206 test_inside(r, p);
2207 }
2208 {
2209 // Size is exclusive
2210 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2211 auto p = Point(200, 200);
2212
2213 test_outside(r, p);
2214 }
2215 {
2216 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2217 auto p = Point(99, 99);
2218
2219 test_outside(r, p);
2220 }
2221 {
2222 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2223 auto p = Point(199, 199);
2224
2225 test_inside(r, p);
2226 }
2227
2228 {
2229 auto r = Rect::MakeMaximum();
2230 auto p = Point(199, 199);
2231
2232 test_inside(r, p);
2233 }
2234 }

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() [271/389]

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

Definition at line 2474 of file rect_unittests.cc.

2474 {
2475 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
2476 ASSERT_TRUE(a.IsFinite()) << label;
2477 ASSERT_TRUE(b.IsFinite()) << label;
2478 ASSERT_FALSE(a.IsEmpty());
2479
2480 for (int i = 1; i < 16; i++) {
2481 // NaN in a produces false
2482 EXPECT_FALSE(swap_nan(a, i).Contains(b)) << label << ", index = " << i;
2483 // NaN in b produces false
2484 EXPECT_TRUE(a.Contains(swap_nan(b, i))) << label << ", index = " << i;
2485 // NaN in both is false
2486 for (int j = 1; j < 16; j++) {
2487 EXPECT_FALSE(swap_nan(a, i).Contains(swap_nan(b, j)))
2488 << label << ", indices = " << i << ", " << j;
2489 }
2490 }
2491 };
2492
2493 auto check_empty_flips = [](const Rect& a, const Rect& b,
2494 const std::string& label) {
2495 ASSERT_FALSE(a.IsEmpty());
2496 // test b rects are allowed to have 0 w/h, but not be backwards
2497 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2498
2499 // unflipped a vs flipped (empty) b yields false
2500 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2501 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2502 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2503
2504 // flipped (empty) a vs unflipped b yields false
2505 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2506 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2507 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2508
2509 // flipped (empty) a vs flipped (empty) b yields empty
2510 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2511 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2512 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2513 };
2514
2515 auto test_inside = [&check_nans, &check_empty_flips](const Rect& a,
2516 const Rect& b) {
2517 ASSERT_FALSE(a.IsEmpty()) << a;
2518 // test b rects are allowed to have 0 w/h, but not be backwards
2519 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2520
2521 std::stringstream stream;
2522 stream << a << " contains " << b;
2523 auto label = stream.str();
2524
2525 EXPECT_TRUE(a.Contains(b)) << label;
2526 check_empty_flips(a, b, label);
2527 check_nans(a, b, label);
2528 };
2529
2530 auto test_not_inside = [&check_nans, &check_empty_flips](const Rect& a,
2531 const Rect& b) {
2532 ASSERT_FALSE(a.IsEmpty()) << a;
2533 // If b was empty, it would be contained and should not be tested with
2534 // this function - use |test_inside| instead.
2535 ASSERT_FALSE(b.IsEmpty()) << b;
2536
2537 std::stringstream stream;
2538 stream << a << " contains " << b;
2539 auto label = stream.str();
2540
2541 EXPECT_FALSE(a.Contains(b)) << label;
2542 check_empty_flips(a, b, label);
2543 check_nans(a, b, label);
2544 };
2545
2546 {
2547 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2548
2549 test_inside(a, a);
2550 }
2551 {
2552 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2553 auto b = Rect::MakeXYWH(0, 0, 0, 0);
2554
2555 test_inside(a, b);
2556 }
2557 {
2558 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2559 auto b = Rect::MakeXYWH(150, 150, 20, 20);
2560
2561 test_inside(a, b);
2562 }
2563 {
2564 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2565 auto b = Rect::MakeXYWH(150, 150, 100, 100);
2566
2567 test_not_inside(a, b);
2568 }
2569 {
2570 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2571 auto b = Rect::MakeXYWH(50, 50, 100, 100);
2572
2573 test_not_inside(a, b);
2574 }
2575 {
2576 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2577 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2578
2579 test_not_inside(a, b);
2580 }
2581 {
2582 auto a = Rect::MakeMaximum();
2583 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2584
2585 test_inside(a, b);
2586 }
2587 }

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() [272/389]

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

Definition at line 654 of file rect_unittests.cc.

654 {
655 // Using fractional-power-of-2 friendly values for equality tests
656 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
657 Rect copy = rect;
658
659 EXPECT_EQ(rect, copy);
660 EXPECT_EQ(copy.GetLeft(), 5.125f);
661 EXPECT_EQ(copy.GetTop(), 10.25f);
662 EXPECT_EQ(copy.GetRight(), 20.625f);
663 EXPECT_EQ(copy.GetBottom(), 25.375f);
664 EXPECT_EQ(copy.GetX(), 5.125f);
665 EXPECT_EQ(copy.GetY(), 10.25f);
666 EXPECT_EQ(copy.GetWidth(), 15.5f);
667 EXPECT_EQ(copy.GetHeight(), 15.125f);
668 EXPECT_FALSE(copy.IsEmpty());
669 EXPECT_TRUE(copy.IsFinite());
670 }

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() [273/389]

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

Definition at line 2682 of file rect_unittests.cc.

2682 {
2683 Rect cull_rect = Rect::MakeLTRB(20, 20, 40, 40);
2684
2685 auto check_nans = [&cull_rect](const Rect& diff_rect,
2686 const std::string& label) {
2687 EXPECT_TRUE(cull_rect.IsFinite()) << label;
2688 EXPECT_TRUE(diff_rect.IsFinite()) << label;
2689
2690 for (int i = 1; i < 16; i++) {
2691 // NaN in cull_rect produces empty
2692 EXPECT_FALSE(swap_nan(cull_rect, i).Cutout(diff_rect).has_value())
2693 << label << ", index " << i;
2694 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(diff_rect), Rect())
2695 << label << ", index " << i;
2696
2697 // NaN in diff_rect is nop
2698 EXPECT_TRUE(cull_rect.Cutout(swap_nan(diff_rect, i)).has_value())
2699 << label << ", index " << i;
2700 EXPECT_EQ(cull_rect.CutoutOrEmpty(swap_nan(diff_rect, i)), cull_rect)
2701 << label << ", index " << i;
2702
2703 for (int j = 1; j < 16; j++) {
2704 // NaN in both is also empty
2705 EXPECT_FALSE(
2706 swap_nan(cull_rect, i).Cutout(swap_nan(diff_rect, j)).has_value())
2707 << label << ", indices " << i << ", " << j;
2708 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(swap_nan(diff_rect, j)),
2709 Rect())
2710 << label << ", indices " << i << ", " << j;
2711 }
2712 }
2713 };
2714
2715 auto check_empty_flips = [&cull_rect](const Rect& diff_rect,
2716 const std::string& label) {
2717 EXPECT_FALSE(cull_rect.IsEmpty()) << label;
2718 EXPECT_FALSE(diff_rect.IsEmpty()) << label;
2719
2720 // unflipped cull_rect vs flipped(empty) diff_rect
2721 // == cull_rect
2722 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2723 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2724 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2725 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2726 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2727 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2728
2729 // flipped(empty) cull_rect vs unflipped diff_rect
2730 // == empty
2731 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2732 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2733 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2734 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2735 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2736 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2737
2738 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2739 // == empty
2740 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2741 << label;
2742 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), Rect())
2743 << label;
2744 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2745 << label;
2746 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), Rect())
2747 << label;
2748 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2749 << label;
2750 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), Rect())
2751 << label;
2752 };
2753
2754 auto non_reducing = [&cull_rect, &check_empty_flips, &check_nans](
2755 const Rect& diff_rect, const std::string& label) {
2756 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2757 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2758 check_empty_flips(diff_rect, label);
2759 check_nans(diff_rect, label);
2760 };
2761
2762 auto reducing = [&cull_rect, &check_empty_flips, &check_nans](
2763 const Rect& diff_rect, const Rect& result_rect,
2764 const std::string& label) {
2765 EXPECT_TRUE(!result_rect.IsEmpty());
2766 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2767 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2768 check_empty_flips(diff_rect, label);
2769 check_nans(diff_rect, label);
2770 };
2771
2772 auto emptying = [&cull_rect, &check_empty_flips, &check_nans](
2773 const Rect& diff_rect, const std::string& label) {
2774 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2775 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), Rect()) << label;
2776 check_empty_flips(diff_rect, label);
2777 check_nans(diff_rect, label);
2778 };
2779
2780 // Skim the corners and edge
2781 non_reducing(Rect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2782 non_reducing(Rect::MakeLTRB(20, 10, 40, 20), "Above");
2783 non_reducing(Rect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2784 non_reducing(Rect::MakeLTRB(40, 20, 50, 40), "Right");
2785 non_reducing(Rect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2786 non_reducing(Rect::MakeLTRB(20, 40, 40, 50), "Below");
2787 non_reducing(Rect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2788 non_reducing(Rect::MakeLTRB(10, 20, 20, 40), "Left");
2789
2790 // Overlap corners
2791 non_reducing(Rect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2792 non_reducing(Rect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2793 non_reducing(Rect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2794 non_reducing(Rect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2795
2796 // Overlap edges, but not across an entire side
2797 non_reducing(Rect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2798 non_reducing(Rect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2799 non_reducing(Rect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2800 non_reducing(Rect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2801 non_reducing(Rect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2802 non_reducing(Rect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2803 non_reducing(Rect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2804 non_reducing(Rect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2805
2806 // Slice all the way through the middle
2807 non_reducing(Rect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2808 non_reducing(Rect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2809
2810 // Slice off each edge
2811 reducing(Rect::MakeLTRB(20, 15, 40, 25), //
2812 Rect::MakeLTRB(20, 25, 40, 40), //
2813 "Slice off top");
2814 reducing(Rect::MakeLTRB(35, 20, 45, 40), //
2815 Rect::MakeLTRB(20, 20, 35, 40), //
2816 "Slice off right");
2817 reducing(Rect::MakeLTRB(20, 35, 40, 45), //
2818 Rect::MakeLTRB(20, 20, 40, 35), //
2819 "Slice off bottom");
2820 reducing(Rect::MakeLTRB(15, 20, 25, 40), //
2821 Rect::MakeLTRB(25, 20, 40, 40), //
2822 "Slice off left");
2823
2824 // cull rect contains diff rect
2825 non_reducing(Rect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2826
2827 // cull rect equals diff rect
2828 emptying(cull_rect, "Perfectly covering");
2829
2830 // diff rect contains cull rect
2831 emptying(Rect::MakeLTRB(15, 15, 45, 45), "Smothering");
2832 }

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() [274/389]

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() [275/389]

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

Definition at line 3024 of file rect_unittests.cc.

3024 {
3025 auto r = Rect::MakeLTRB(1, 2, 3, 4);
3026
3027 EXPECT_EQ(r.GetLeft(), 1);
3028 EXPECT_EQ(r.GetTop(), 2);
3029 EXPECT_EQ(r.GetRight(), 3);
3030 EXPECT_EQ(r.GetBottom(), 4);
3031
3032 EXPECT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
3033 EXPECT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
3034 EXPECT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
3035 EXPECT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
3036 }

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

## ◆ TEST() [276/389]

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

Definition at line 795 of file rect_unittests.cc.

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

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

## ◆ TEST() [277/389]

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() [278/389]

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

Definition at line 1236 of file rect_unittests.cc.

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

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

## ◆ TEST() [279/389]

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

Definition at line 640 of file rect_unittests.cc.

640 {
641 EXPECT_EQ(Rect(Rect::MakeXYWH(2, 3, 7, 15)),
642 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
643 EXPECT_EQ(Rect(Rect::MakeLTRB(2, 3, 7, 15)),
644 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
645 }

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

## ◆ TEST() [280/389]

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

Definition at line 1020 of file rect_unittests.cc.

1020 {
1021 {
1022 // Checks for expected matrix values
1023
1024 auto r = Rect::MakeXYWH(100, 200, 200, 400);
1025
1026 EXPECT_EQ(r.GetNormalizingTransform(),
1027 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1028 Matrix::MakeTranslation({-100, -200}));
1029 }
1030
1031 {
1032 // Checks for expected transform of points relative to the rect
1033
1034 auto r = Rect::MakeLTRB(300, 500, 400, 700);
1035 auto m = r.GetNormalizingTransform();
1036
1037 // The 4 corners of the rect => (0, 0) to (1, 1)
1038 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1039 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1040 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1041 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1042
1043 // The center => (0.5, 0.5)
1044 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1045
1046 // Outside the 4 corners => (-1, -1) to (2, 2)
1047 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1048 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1049 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1050 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1051 }
1052
1053 {
1054 // Checks for behavior with empty rects
1055
1056 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1057
1058 // Empty for width and/or height == 0
1059 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1060 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1061 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1062
1063 // Empty for width and/or height < 0
1064 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1065 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1066 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1067 }
1068
1069 {
1070 // Checks for behavior with non-finite rects
1071
1072 auto z = Matrix::MakeScale({0.0, 0.0, 1.0});
1073 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1074 auto inf = std::numeric_limits<Scalar>::infinity();
1075
1076 // Non-finite for width and/or height == nan
1077 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
1078 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
1079 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
1080
1081 // Non-finite for width and/or height == inf
1082 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
1083 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
1084 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
1085
1086 // Non-finite for width and/or height == -inf
1087 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
1088 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
1089 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
1090
1091 // Non-finite for origin X and/or Y == nan
1092 EXPECT_EQ(Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
1093 EXPECT_EQ(Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
1094 EXPECT_EQ(Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
1095
1096 // Non-finite for origin X and/or Y == inf
1097 EXPECT_EQ(Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
1098 EXPECT_EQ(Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
1099 EXPECT_EQ(Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
1100
1101 // Non-finite for origin X and/or Y == -inf
1102 EXPECT_EQ(Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
1103 EXPECT_EQ(Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
1104 EXPECT_EQ(Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
1105 }
1106 }

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

## ◆ TEST() [281/389]

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

Definition at line 2953 of file rect_unittests.cc.

2953 {
2954 {
2955 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2956 auto points = r.GetPoints();
2957 EXPECT_POINT_NEAR(points[0], Point(100, 200));
2958 EXPECT_POINT_NEAR(points[1], Point(400, 200));
2959 EXPECT_POINT_NEAR(points[2], Point(100, 600));
2960 EXPECT_POINT_NEAR(points[3], Point(400, 600));
2961 }
2962
2963 {
2964 Rect r = Rect::MakeMaximum();
2965 auto points = r.GetPoints();
2966 EXPECT_EQ(points[0], Point(std::numeric_limits<float>::lowest(),
2967 std::numeric_limits<float>::lowest()));
2968 EXPECT_EQ(points[1], Point(std::numeric_limits<float>::max(),
2969 std::numeric_limits<float>::lowest()));
2970 EXPECT_EQ(points[2], Point(std::numeric_limits<float>::lowest(),
2971 std::numeric_limits<float>::max()));
2972 EXPECT_EQ(points[3], Point(std::numeric_limits<float>::max(),
2973 std::numeric_limits<float>::max()));
2974 }
2975 }

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

## ◆ TEST() [282/389]

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

Definition at line 3010 of file rect_unittests.cc.

3010 {
3011 {
3012 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
3013 auto actual = r.GetPositive();
3014 EXPECT_RECT_NEAR(r, actual);
3015 }
3016 {
3017 Rect r = Rect::MakeXYWH(100, 200, -100, -100);
3018 auto actual = r.GetPositive();
3019 Rect expected = Rect::MakeXYWH(0, 100, 100, 100);
3020 EXPECT_RECT_NEAR(expected, actual);
3021 }
3022 }

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

## ◆ TEST() [283/389]

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

Definition at line 2984 of file rect_unittests.cc.

2984 {
2985 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2986 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
2987 EXPECT_POINT_NEAR(points[0], Point(110, 220));
2988 EXPECT_POINT_NEAR(points[1], Point(410, 220));
2989 EXPECT_POINT_NEAR(points[2], Point(110, 620));
2990 EXPECT_POINT_NEAR(points[3], Point(410, 620));
2991 }

References EXPECT_POINT_NEAR, impeller::TRect< T >::GetTransformedPoints(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [284/389]

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

Definition at line 1611 of file rect_unittests.cc.

1611 {
1612 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1613 ASSERT_TRUE(a.IsFinite()) << label;
1614 ASSERT_TRUE(b.IsFinite()) << label;
1615
1616 for (int i = 1; i < 16; i++) {
1617 // NaN in a produces empty
1618 EXPECT_FALSE(swap_nan(a, i).Intersection(b).has_value())
1619 << label << ", index = " << i;
1620 // NaN in b produces empty
1621 EXPECT_FALSE(a.Intersection(swap_nan(b, i)).has_value())
1622 << label << ", index = " << i;
1623 // NaN in both is empty
1624 for (int j = 1; j < 16; j++) {
1625 EXPECT_FALSE(swap_nan(a, i).Intersection(swap_nan(b, j)).has_value())
1626 << label << ", indices = " << i << ", " << j;
1627 }
1628 }
1629 };
1630
1631 auto check_empty_flips = [](const Rect& a, const Rect& b,
1632 const std::string& label) {
1633 ASSERT_FALSE(a.IsEmpty());
1634 // b is allowed to be empty
1635
1636 // unflipped a vs flipped (empty) b yields a
1637 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1638 EXPECT_TRUE(a.IntersectionOrEmpty(flip_lr(b)).IsEmpty()) << label;
1639 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1640 EXPECT_TRUE(a.IntersectionOrEmpty(flip_tb(b)).IsEmpty()) << label;
1641 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1642 EXPECT_TRUE(a.IntersectionOrEmpty(flip_lrtb(b)).IsEmpty()) << label;
1643
1644 // flipped (empty) a vs unflipped b yields b
1645 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1646 EXPECT_TRUE(flip_lr(a).IntersectionOrEmpty(b).IsEmpty()) << label;
1647 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1648 EXPECT_TRUE(flip_tb(a).IntersectionOrEmpty(b).IsEmpty()) << label;
1649 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1650 EXPECT_TRUE(flip_lrtb(a).IntersectionOrEmpty(b).IsEmpty()) << label;
1651
1652 // flipped (empty) a vs flipped (empty) b yields empty
1653 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1654 EXPECT_TRUE(flip_lr(a).IntersectionOrEmpty(flip_lr(b)).IsEmpty()) << label;
1655 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1656 EXPECT_TRUE(flip_tb(a).IntersectionOrEmpty(flip_tb(b)).IsEmpty()) << label;
1657 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1658 EXPECT_TRUE(flip_lrtb(a).IntersectionOrEmpty(flip_lrtb(b)).IsEmpty())
1659 << label;
1660 };
1661
1662 auto test_non_empty = [&check_nans, &check_empty_flips](
1663 const Rect& a, const Rect& b, const Rect& result) {
1664 ASSERT_FALSE(a.IsEmpty()) << a;
1665 // b is allowed to be empty
1666
1667 std::stringstream stream;
1668 stream << a << " union " << b;
1669 auto label = stream.str();
1670
1671 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1672 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1673 EXPECT_EQ(a.Intersection(b), result) << label;
1674 EXPECT_EQ(b.Intersection(a), result) << label;
1675 check_empty_flips(a, b, label);
1676 check_nans(a, b, label);
1677 };
1678
1679 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1680 const Rect& b) {
1681 ASSERT_FALSE(a.IsEmpty()) << a;
1682 // b is allowed to be empty
1683
1684 std::stringstream stream;
1685 stream << a << " union " << b;
1686 auto label = stream.str();
1687
1688 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1689 EXPECT_TRUE(a.IntersectionOrEmpty(b).IsEmpty()) << label;
1690 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1691 EXPECT_TRUE(b.IntersectionOrEmpty(a).IsEmpty()) << label;
1692 check_empty_flips(a, b, label);
1693 check_nans(a, b, label);
1694 };
1695
1696 {
1697 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1698 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1699
1700 test_empty(a, b);
1701 }
1702
1703 {
1704 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1705 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1706
1707 test_empty(a, b);
1708 }
1709
1710 {
1711 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1712 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1713 auto expected = Rect::MakeXYWH(10, 10, 90, 90);
1714
1715 test_non_empty(a, b, expected);
1716 }
1717
1718 {
1719 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1720 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1721
1722 test_empty(a, b);
1723 }
1724
1725 {
1726 auto a = Rect::MakeMaximum();
1727 auto b = Rect::MakeXYWH(10, 10, 300, 300);
1728
1729 test_non_empty(a, b, b);
1730 }
1731
1732 {
1733 auto a = Rect::MakeMaximum();
1734 auto b = Rect::MakeMaximum();
1735
1736 test_non_empty(a, b, Rect::MakeMaximum());
1737 }
1738 }

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

## ◆ TEST() [285/389]

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

Definition at line 1945 of file rect_unittests.cc.

1945 {
1946 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1947 ASSERT_TRUE(a.IsFinite()) << label;
1948 ASSERT_TRUE(b.IsFinite()) << label;
1949
1950 for (int i = 1; i < 16; i++) {
1951 // NaN in a produces b
1952 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(b))
1953 << label << ", index = " << i;
1954 // NaN in b produces a
1955 EXPECT_FALSE(a.IntersectsWithRect(swap_nan(b, i)))
1956 << label << ", index = " << i;
1957 // NaN in both is empty
1958 for (int j = 1; j < 16; j++) {
1959 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(swap_nan(b, j)))
1960 << label << ", indices = " << i << ", " << j;
1961 }
1962 }
1963 };
1964
1965 auto check_empty_flips = [](const Rect& a, const Rect& b,
1966 const std::string& label) {
1967 ASSERT_FALSE(a.IsEmpty());
1968 // b is allowed to be empty
1969
1970 // unflipped a vs flipped (empty) b yields a
1971 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
1972 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
1973 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
1974
1975 // flipped (empty) a vs unflipped b yields b
1976 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
1977 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
1978 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
1979
1980 // flipped (empty) a vs flipped (empty) b yields empty
1981 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
1982 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
1983 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
1984 };
1985
1986 auto test_non_empty = [&check_nans, &check_empty_flips](const Rect& a,
1987 const Rect& b) {
1988 ASSERT_FALSE(a.IsEmpty()) << a;
1989 // b is allowed to be empty
1990
1991 std::stringstream stream;
1992 stream << a << " union " << b;
1993 auto label = stream.str();
1994
1995 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
1996 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
1997 check_empty_flips(a, b, label);
1998 check_nans(a, b, label);
1999 };
2000
2001 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
2002 const Rect& b) {
2003 ASSERT_FALSE(a.IsEmpty()) << a;
2004 // b is allowed to be empty
2005
2006 std::stringstream stream;
2007 stream << a << " union " << b;
2008 auto label = stream.str();
2009
2010 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
2011 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
2012 check_empty_flips(a, b, label);
2013 check_nans(a, b, label);
2014 };
2015
2016 {
2017 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2018 auto b = Rect::MakeXYWH(0, 0, 0, 0);
2019
2020 test_empty(a, b);
2021 }
2022
2023 {
2024 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2025 auto b = Rect::MakeXYWH(10, 10, 0, 0);
2026
2027 test_empty(a, b);
2028 }
2029
2030 {
2031 auto a = Rect::MakeXYWH(0, 0, 100, 100);
2032 auto b = Rect::MakeXYWH(10, 10, 100, 100);
2033
2034 test_non_empty(a, b);
2035 }
2036
2037 {
2038 auto a = Rect::MakeXYWH(0, 0, 100, 100);
2039 auto b = Rect::MakeXYWH(100, 100, 100, 100);
2040
2041 test_empty(a, b);
2042 }
2043
2044 {
2045 auto a = Rect::MakeMaximum();
2046 auto b = Rect::MakeXYWH(10, 10, 100, 100);
2047
2048 test_non_empty(a, b);
2049 }
2050
2051 {
2052 auto a = Rect::MakeMaximum();
2053 auto b = Rect::MakeMaximum();
2054
2055 test_non_empty(a, b);
2056 }
2057 }

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() [286/389]

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

Definition at line 606 of file rect_unittests.cc.

606 {
607 Rect rect = Rect::MakeMaximum();
608 auto inf = std::numeric_limits<Scalar>::infinity();
609 auto min = std::numeric_limits<Scalar>::lowest();
610 auto max = std::numeric_limits<Scalar>::max();
611
612 EXPECT_EQ(rect.GetLeft(), min);
613 EXPECT_EQ(rect.GetTop(), min);
614 EXPECT_EQ(rect.GetRight(), max);
615 EXPECT_EQ(rect.GetBottom(), max);
616 EXPECT_EQ(rect.GetX(), min);
617 EXPECT_EQ(rect.GetY(), min);
618 EXPECT_EQ(rect.GetWidth(), inf);
619 EXPECT_EQ(rect.GetHeight(), inf);
620 EXPECT_FALSE(rect.IsEmpty());
621 EXPECT_TRUE(rect.IsFinite());
622 }

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() [287/389]

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

Definition at line 2993 of file rect_unittests.cc.

2993 {
2994 {
2995 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
2996 auto r = Rect::MakePointBounds(points.begin(), points.end());
2997 auto expected = Rect::MakeXYWH(0, -1, 4, 7);
2998 EXPECT_TRUE(r.has_value());
2999 if (r.has_value()) {
3000 EXPECT_RECT_NEAR(r.value(), expected);
3001 }
3002 }
3003 {
3004 std::vector<Point> points;
3005 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
3006 EXPECT_FALSE(r.has_value());
3007 }
3008 }

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

## ◆ TEST() [288/389]

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

Definition at line 576 of file rect_unittests.cc.

576 {
577 {
578 Size s(100, 200);
579 Rect r = Rect::MakeSize(s);
580 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
581 EXPECT_RECT_NEAR(r, expected);
582 }
583
584 {
585 ISize s(100, 200);
586 Rect r = Rect::MakeSize(s);
587 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
588 EXPECT_RECT_NEAR(r, expected);
589 }
590
591 {
592 Size s(100, 200);
593 IRect r = IRect::MakeSize(s);
594 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
595 EXPECT_EQ(r, expected);
596 }
597
598 {
599 ISize s(100, 200);
600 IRect r = IRect::MakeSize(s);
601 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
602 EXPECT_EQ(r, expected);
603 }
604 }

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

## ◆ TEST() [289/389]

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

Definition at line 688 of file rect_unittests.cc.

688 {
689 {
690 Rect r = Rect::MakeOriginSize({10, 20}, {50, 40});
691 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
692 EXPECT_EQ(r.GetSize(), Size(50, 40));
693 EXPECT_EQ(r.GetX(), 10);
694 EXPECT_EQ(r.GetY(), 20);
695 EXPECT_EQ(r.GetWidth(), 50);
696 EXPECT_EQ(r.GetHeight(), 40);
697 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
698 EXPECT_EQ(r.GetXYWH(), expected_array);
699 }
700
701 {
702 Rect r = Rect::MakeLTRB(10, 20, 50, 40);
703 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
704 EXPECT_EQ(r.GetSize(), Size(40, 20));
705 EXPECT_EQ(r.GetX(), 10);
706 EXPECT_EQ(r.GetY(), 20);
707 EXPECT_EQ(r.GetWidth(), 40);
708 EXPECT_EQ(r.GetHeight(), 20);
709 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
710 EXPECT_EQ(r.GetXYWH(), expected_array);
711 }
712 }

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() [290/389]

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

Definition at line 370 of file rect_unittests.cc.

370 {
371 auto min = std::numeric_limits<Scalar>::lowest();
372 auto max = std::numeric_limits<Scalar>::max();
373 auto inf = std::numeric_limits<Scalar>::infinity();
374
375 // 8 cases:
376 // finite negative X, max W
377 // ~min X, ~max W
378 // finite negative Y, max H
379 // ~min Y, ~max H
380 // finite positive X, min W
381 // ~min X, ~min W
382 // finite positive Y, min H
383 // ~min Y, ~min H
384
385 // a small finite value subtracted from a max value will remain max
386 // a very large finite value (like min) subtracted from max will go to inf
387
388 {
389 Rect rect = Rect::MakeLTRB(-5.0f, 10.0f, max, 25.0f);
390
391 EXPECT_EQ(rect.GetLeft(), -5.0f);
392 EXPECT_EQ(rect.GetTop(), 10.0f);
393 EXPECT_EQ(rect.GetRight(), max);
394 EXPECT_EQ(rect.GetBottom(), 25.0f);
395 EXPECT_EQ(rect.GetX(), -5.0f);
396 EXPECT_EQ(rect.GetY(), 10.0f);
397 EXPECT_EQ(rect.GetWidth(), max);
398 EXPECT_EQ(rect.GetHeight(), 15.0f);
399 EXPECT_FALSE(rect.IsEmpty());
400 EXPECT_TRUE(rect.IsFinite());
401 }
402
403 {
404 Rect rect = Rect::MakeLTRB(min + 5.0f, 10.0f, max - 5.0f, 25.0f);
405
406 EXPECT_EQ(rect.GetLeft(), min + 5.0f);
407 EXPECT_EQ(rect.GetTop(), 10.0f);
408 EXPECT_EQ(rect.GetRight(), max - 5.0f);
409 EXPECT_EQ(rect.GetBottom(), 25.0f);
410 EXPECT_EQ(rect.GetX(), min + 5.0f);
411 EXPECT_EQ(rect.GetY(), 10.0f);
412 EXPECT_EQ(rect.GetWidth(), inf);
413 EXPECT_EQ(rect.GetHeight(), 15.0f);
414 EXPECT_FALSE(rect.IsEmpty());
415 EXPECT_TRUE(rect.IsFinite());
416 }
417
418 {
419 Rect rect = Rect::MakeLTRB(5.0f, -10.0f, 20.0f, max);
420
421 EXPECT_EQ(rect.GetLeft(), 5.0f);
422 EXPECT_EQ(rect.GetTop(), -10.0f);
423 EXPECT_EQ(rect.GetRight(), 20.0f);
424 EXPECT_EQ(rect.GetBottom(), max);
425 EXPECT_EQ(rect.GetX(), 5.0f);
426 EXPECT_EQ(rect.GetY(), -10.0f);
427 EXPECT_EQ(rect.GetWidth(), 15.0f);
428 EXPECT_EQ(rect.GetHeight(), max);
429 EXPECT_FALSE(rect.IsEmpty());
430 EXPECT_TRUE(rect.IsFinite());
431 }
432
433 {
434 Rect rect = Rect::MakeLTRB(5.0f, min + 10.0f, 20.0f, max - 15.0f);
435
436 EXPECT_EQ(rect.GetLeft(), 5.0f);
437 EXPECT_EQ(rect.GetTop(), min + 10.0f);
438 EXPECT_EQ(rect.GetRight(), 20.0f);
439 EXPECT_EQ(rect.GetBottom(), max - 15.0f);
440 EXPECT_EQ(rect.GetX(), 5.0f);
441 EXPECT_EQ(rect.GetY(), min + 10.0f);
442 EXPECT_EQ(rect.GetWidth(), 15.0f);
443 EXPECT_EQ(rect.GetHeight(), inf);
444 EXPECT_FALSE(rect.IsEmpty());
445 EXPECT_TRUE(rect.IsFinite());
446 }
447
448 {
449 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, min, 25.0f);
450
451 EXPECT_EQ(rect.GetLeft(), 5.0f);
452 EXPECT_EQ(rect.GetTop(), 10.0f);
453 EXPECT_EQ(rect.GetRight(), min);
454 EXPECT_EQ(rect.GetBottom(), 25.0f);
455 EXPECT_EQ(rect.GetX(), 5.0f);
456 EXPECT_EQ(rect.GetY(), 10.0f);
457 EXPECT_EQ(rect.GetWidth(), min);
458 EXPECT_EQ(rect.GetHeight(), 15.0f);
459 EXPECT_TRUE(rect.IsEmpty());
460 EXPECT_TRUE(rect.IsFinite());
461 }
462
463 {
464 Rect rect = Rect::MakeLTRB(max - 5.0f, 10.0f, min + 10.0f, 25.0f);
465
466 EXPECT_EQ(rect.GetLeft(), max - 5.0f);
467 EXPECT_EQ(rect.GetTop(), 10.0f);
468 EXPECT_EQ(rect.GetRight(), min + 10.0f);
469 EXPECT_EQ(rect.GetBottom(), 25.0f);
470 EXPECT_EQ(rect.GetX(), max - 5.0f);
471 EXPECT_EQ(rect.GetY(), 10.0f);
472 EXPECT_EQ(rect.GetWidth(), -inf);
473 EXPECT_EQ(rect.GetHeight(), 15.0f);
474 EXPECT_TRUE(rect.IsEmpty());
475 EXPECT_TRUE(rect.IsFinite());
476 }
477
478 {
479 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, 20.0f, min);
480
481 EXPECT_EQ(rect.GetLeft(), 5.0f);
482 EXPECT_EQ(rect.GetTop(), 10.0f);
483 EXPECT_EQ(rect.GetRight(), 20.0f);
484 EXPECT_EQ(rect.GetBottom(), min);
485 EXPECT_EQ(rect.GetX(), 5.0f);
486 EXPECT_EQ(rect.GetY(), 10.0f);
487 EXPECT_EQ(rect.GetWidth(), 15.0f);
488 EXPECT_EQ(rect.GetHeight(), min);
489 EXPECT_TRUE(rect.IsEmpty());
490 EXPECT_TRUE(rect.IsFinite());
491 }
492
493 {
494 Rect rect = Rect::MakeLTRB(5.0f, max - 5.0f, 20.0f, min + 10.0f);
495
496 EXPECT_EQ(rect.GetLeft(), 5.0f);
497 EXPECT_EQ(rect.GetTop(), max - 5.0f);
498 EXPECT_EQ(rect.GetRight(), 20.0f);
499 EXPECT_EQ(rect.GetBottom(), min + 10.0f);
500 EXPECT_EQ(rect.GetX(), 5.0f);
501 EXPECT_EQ(rect.GetY(), max - 5.0f);
502 EXPECT_EQ(rect.GetWidth(), 15.0f);
503 EXPECT_EQ(rect.GetHeight(), -inf);
504 EXPECT_TRUE(rect.IsEmpty());
505 EXPECT_TRUE(rect.IsFinite());
506 }
507 }

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() [291/389]

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

Definition at line 164 of file rect_unittests.cc.

164 {
165 auto min = std::numeric_limits<Scalar>::lowest();
166 auto max = std::numeric_limits<Scalar>::max();
167 auto inf = std::numeric_limits<Scalar>::infinity();
168
169 // 8 cases:
170 // finite X, max W
171 // max X, max W
172 // finite Y, max H
173 // max Y, max H
174 // finite X, min W
175 // min X, min W
176 // finite Y, min H
177 // min Y, min H
178
179 // a small finite value added to a max value will remain max
180 // a very large finite value (like max) added to max will go to infinity
181
182 {
183 Rect rect = Rect::MakeXYWH(5.0, 10.0f, max, 15.0f);
184
185 EXPECT_EQ(rect.GetLeft(), 5.0f);
186 EXPECT_EQ(rect.GetTop(), 10.0f);
187 EXPECT_EQ(rect.GetRight(), max);
188 EXPECT_EQ(rect.GetBottom(), 25.0f);
189 EXPECT_EQ(rect.GetX(), 5.0f);
190 EXPECT_EQ(rect.GetY(), 10.0f);
191 EXPECT_EQ(rect.GetWidth(), max);
192 EXPECT_EQ(rect.GetHeight(), 15.0f);
193 EXPECT_FALSE(rect.IsEmpty());
194 EXPECT_TRUE(rect.IsFinite());
195 }
196
197 {
198 Rect rect = Rect::MakeXYWH(max, 10.0f, max, 15.0f);
199
200 EXPECT_EQ(rect.GetLeft(), max);
201 EXPECT_EQ(rect.GetTop(), 10.0f);
202 EXPECT_EQ(rect.GetRight(), inf);
203 EXPECT_EQ(rect.GetBottom(), 25.0f);
204 EXPECT_EQ(rect.GetX(), max);
205 EXPECT_EQ(rect.GetY(), 10.0f);
206 EXPECT_EQ(rect.GetWidth(), inf);
207 EXPECT_EQ(rect.GetHeight(), 15.0f);
208 EXPECT_FALSE(rect.IsEmpty());
209 EXPECT_FALSE(rect.IsFinite());
210 }
211
212 {
213 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, max);
214
215 EXPECT_EQ(rect.GetLeft(), 5.0f);
216 EXPECT_EQ(rect.GetTop(), 10.0f);
217 EXPECT_EQ(rect.GetRight(), 25.0f);
218 EXPECT_EQ(rect.GetBottom(), max);
219 EXPECT_EQ(rect.GetX(), 5.0f);
220 EXPECT_EQ(rect.GetY(), 10.0f);
221 EXPECT_EQ(rect.GetWidth(), 20.0f);
222 EXPECT_EQ(rect.GetHeight(), max);
223 EXPECT_FALSE(rect.IsEmpty());
224 EXPECT_TRUE(rect.IsFinite());
225 }
226
227 {
228 Rect rect = Rect::MakeXYWH(5.0f, max, 20.0f, max);
229
230 EXPECT_EQ(rect.GetLeft(), 5.0f);
231 EXPECT_EQ(rect.GetTop(), max);
232 EXPECT_EQ(rect.GetRight(), 25.0f);
233 EXPECT_EQ(rect.GetBottom(), inf);
234 EXPECT_EQ(rect.GetX(), 5.0f);
235 EXPECT_EQ(rect.GetY(), max);
236 EXPECT_EQ(rect.GetWidth(), 20.0f);
237 EXPECT_EQ(rect.GetHeight(), inf);
238 EXPECT_FALSE(rect.IsEmpty());
239 EXPECT_FALSE(rect.IsFinite());
240 }
241
242 {
243 Rect rect = Rect::MakeXYWH(5.0, 10.0f, min, 15.0f);
244
245 EXPECT_EQ(rect.GetLeft(), 5.0f);
246 EXPECT_EQ(rect.GetTop(), 10.0f);
247 EXPECT_EQ(rect.GetRight(), min);
248 EXPECT_EQ(rect.GetBottom(), 25.0f);
249 EXPECT_EQ(rect.GetX(), 5.0f);
250 EXPECT_EQ(rect.GetY(), 10.0f);
251 EXPECT_EQ(rect.GetWidth(), min);
252 EXPECT_EQ(rect.GetHeight(), 15.0f);
253 EXPECT_TRUE(rect.IsEmpty());
254 EXPECT_TRUE(rect.IsFinite());
255 }
256
257 {
258 Rect rect = Rect::MakeXYWH(min, 10.0f, min, 15.0f);
259
260 EXPECT_EQ(rect.GetLeft(), min);
261 EXPECT_EQ(rect.GetTop(), 10.0f);
262 EXPECT_EQ(rect.GetRight(), -inf);
263 EXPECT_EQ(rect.GetBottom(), 25.0f);
264 EXPECT_EQ(rect.GetX(), min);
265 EXPECT_EQ(rect.GetY(), 10.0f);
266 EXPECT_EQ(rect.GetWidth(), -inf);
267 EXPECT_EQ(rect.GetHeight(), 15.0f);
268 EXPECT_TRUE(rect.IsEmpty());
269 EXPECT_FALSE(rect.IsFinite());
270 }
271
272 {
273 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, min);
274
275 EXPECT_EQ(rect.GetLeft(), 5.0f);
276 EXPECT_EQ(rect.GetTop(), 10.0f);
277 EXPECT_EQ(rect.GetRight(), 25.0f);
278 EXPECT_EQ(rect.GetBottom(), min);
279 EXPECT_EQ(rect.GetX(), 5.0f);
280 EXPECT_EQ(rect.GetY(), 10.0f);
281 EXPECT_EQ(rect.GetWidth(), 20.0f);
282 EXPECT_EQ(rect.GetHeight(), min);
283 EXPECT_TRUE(rect.IsEmpty());
284 EXPECT_TRUE(rect.IsFinite());
285 }
286
287 {
288 Rect rect = Rect::MakeXYWH(5.0f, min, 20.0f, min);
289
290 EXPECT_EQ(rect.GetLeft(), 5.0f);
291 EXPECT_EQ(rect.GetTop(), min);
292 EXPECT_EQ(rect.GetRight(), 25.0f);
293 EXPECT_EQ(rect.GetBottom(), -inf);
294 EXPECT_EQ(rect.GetX(), 5.0f);
295 EXPECT_EQ(rect.GetY(), min);
296 EXPECT_EQ(rect.GetWidth(), 20.0f);
297 EXPECT_EQ(rect.GetHeight(), -inf);
298 EXPECT_TRUE(rect.IsEmpty());
299 EXPECT_FALSE(rect.IsFinite());
300 }
301 }

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() [292/389]

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

Definition at line 3038 of file rect_unittests.cc.

3038 {
3039 {
3040 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
3041 auto actual = r.Project(r);
3042 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
3043 EXPECT_RECT_NEAR(expected, actual);
3044 }
3045 {
3046 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
3047 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
3048 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
3049 EXPECT_RECT_NEAR(expected, actual);
3050 }
3051 }

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

## ◆ TEST() [293/389]

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

Definition at line 3077 of file rect_unittests.cc.

3077 {
3078 {
3079 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3080 EXPECT_EQ(Rect::Round(r), r);
3081 }
3082 {
3083 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3084 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-100, -200, 300, 400));
3085 }
3086 {
3087 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3088 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-101, -201, 301, 401));
3089 }
3090 }

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

## ◆ TEST() [294/389]

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

Definition at line 3053 of file rect_unittests.cc.

3053 {
3054 {
3055 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3056 EXPECT_EQ(Rect::RoundOut(r), r);
3057 }
3058 {
3059 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3060 EXPECT_EQ(Rect::RoundOut(r), Rect::MakeLTRB(-101, -201, 301, 401));
3061 }
3062 }

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

## ◆ TEST() [295/389]

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

Definition at line 740 of file rect_unittests.cc.

740 {
741 Rect rect;
742
743 EXPECT_EQ(Rect::RoundOut(rect), Rect());
744
745 EXPECT_EQ(IRect::RoundOut(rect), IRect());
746 }

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

## ◆ TEST() [296/389]

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

Definition at line 748 of file rect_unittests.cc.

748 {
749 Rect rect = Rect::MakeLTRB(5.125f, 10.75f, 20.625f, 25.375f);
750
751 EXPECT_EQ(Rect::RoundOut(rect), Rect::MakeLTRB(5.0f, 10.0f, 21.0f, 26.0f));
752
753 EXPECT_EQ(IRect::RoundOut(rect), IRect::MakeLTRB(5, 10, 21, 26));
754 }

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

## ◆ TEST() [297/389]

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

Definition at line 756 of file rect_unittests.cc.

756 {
757 auto test = [](int corners) {
758 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
759 Scalar l, t, r, b;
760 int64_t il, it, ir, ib;
761 l = il = 50;
762 t = it = 50;
763 r = ir = 80;
764 b = ib = 80;
765 if ((corners & (1 << 0)) != 0) {
766 l = -1E20;
767 il = std::numeric_limits<int64_t>::min();
768 }
769 if ((corners & (1 << 1)) != 0) {
770 t = -1E20;
771 it = std::numeric_limits<int64_t>::min();
772 }
773 if ((corners & (1 << 2)) != 0) {
774 r = +1E20;
775 ir = std::numeric_limits<int64_t>::max();
776 }
777 if ((corners & (1 << 3)) != 0) {
778 b = +1E20;
779 ib = std::numeric_limits<int64_t>::max();
780 }
781
782 Rect rect = Rect::MakeLTRB(l, t, r, b);
783 IRect irect = IRect::RoundOut(rect);
784 EXPECT_EQ(irect.GetLeft(), il) << corners;
785 EXPECT_EQ(irect.GetTop(), it) << corners;
786 EXPECT_EQ(irect.GetRight(), ir) << corners;
787 EXPECT_EQ(irect.GetBottom(), ib) << corners;
788 };
789
790 for (int corners = 0; corners <= 15; corners++) {
791 test(corners);
792 }
793 }

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() [298/389]

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

Definition at line 915 of file rect_unittests.cc.

915 {
916 auto test1 = [](Rect rect, Scalar scale) {
917 Rect expected = Rect::MakeXYWH(rect.GetX() * scale, //
918 rect.GetY() * scale, //
919 rect.GetWidth() * scale, //
920 rect.GetHeight() * scale);
921
922 EXPECT_RECT_NEAR(rect.Scale(scale), expected) //
923 << rect << " * " << scale;
924 EXPECT_RECT_NEAR(rect.Scale(scale, scale), expected) //
925 << rect << " * " << scale;
926 EXPECT_RECT_NEAR(rect.Scale(Point(scale, scale)), expected) //
927 << rect << " * " << scale;
928 EXPECT_RECT_NEAR(rect.Scale(Size(scale, scale)), expected) //
929 << rect << " * " << scale;
930 };
931
932 auto test2 = [&test1](Rect rect, Scalar scale_x, Scalar scale_y) {
933 Rect expected = Rect::MakeXYWH(rect.GetX() * scale_x, //
934 rect.GetY() * scale_y, //
935 rect.GetWidth() * scale_x, //
936 rect.GetHeight() * scale_y);
937
938 EXPECT_RECT_NEAR(rect.Scale(scale_x, scale_y), expected) //
939 << rect << " * " << scale_x << ", " << scale_y;
940 EXPECT_RECT_NEAR(rect.Scale(Point(scale_x, scale_y)), expected) //
941 << rect << " * " << scale_x << ", " << scale_y;
942 EXPECT_RECT_NEAR(rect.Scale(Size(scale_x, scale_y)), expected) //
943 << rect << " * " << scale_x << ", " << scale_y;
944
945 test1(rect, scale_x);
946 test1(rect, scale_y);
947 };
948
949 test2(Rect::MakeLTRB(10, 15, 100, 150), 1.0, 0.0);
950 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 1.0);
951 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 0.0);
952 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, 3.5);
953 test2(Rect::MakeLTRB(10, 15, 100, 150), 3.5, 2.5);
954 test2(Rect::MakeLTRB(10, 15, -100, 150), 2.5, 3.5);
955 test2(Rect::MakeLTRB(10, 15, 100, -150), 2.5, 3.5);
956 test2(Rect::MakeLTRB(10, 15, 100, 150), -2.5, 3.5);
957 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, -3.5);
958 }

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() [299/389]

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

Definition at line 2977 of file rect_unittests.cc.

2977 {
2978 auto r = Rect::MakeLTRB(0, 0, 100, 100);
2979
2980 EXPECT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
2981 EXPECT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
2982 }

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

## ◆ TEST() [300/389]

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() [301/389]

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

Definition at line 133 of file rect_unittests.cc.

133 {
134 // Using fractional-power-of-2 friendly values for equality tests
135 Rect rect = Rect::MakeWH(15.5f, 15.125f);
136
137 EXPECT_EQ(rect.GetLeft(), 0.0f);
138 EXPECT_EQ(rect.GetTop(), 0.0f);
139 EXPECT_EQ(rect.GetRight(), 15.5f);
140 EXPECT_EQ(rect.GetBottom(), 15.125f);
141 EXPECT_EQ(rect.GetX(), 0.0f);
142 EXPECT_EQ(rect.GetY(), 0.0f);
143 EXPECT_EQ(rect.GetWidth(), 15.5f);
144 EXPECT_EQ(rect.GetHeight(), 15.125f);
145 EXPECT_FALSE(rect.IsEmpty());
146 EXPECT_TRUE(rect.IsFinite());
147 }

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

## ◆ TEST() [302/389]

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() [303/389]

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

Definition at line 1344 of file rect_unittests.cc.

1344 {
1345 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1346 ASSERT_TRUE(a.IsFinite()) << label;
1347 ASSERT_TRUE(b.IsFinite()) << label;
1348 ASSERT_FALSE(a.Union(b).IsEmpty());
1349
1350 for (int i = 1; i < 16; i++) {
1351 // NaN in a produces b
1352 EXPECT_EQ(swap_nan(a, i).Union(b), b) << label << ", index = " << i;
1353 // NaN in b produces a
1354 EXPECT_EQ(a.Union(swap_nan(b, i)), a) << label << ", index = " << i;
1355 // NaN in both is empty
1356 for (int j = 1; j < 16; j++) {
1357 EXPECT_TRUE(swap_nan(a, i).Union(swap_nan(b, j)).IsEmpty())
1358 << label << ", indices = " << i << ", " << j;
1359 }
1360 }
1361 };
1362
1363 auto check_empty_flips = [](const Rect& a, const Rect& b,
1364 const std::string& label) {
1365 ASSERT_FALSE(a.IsEmpty());
1366 // b is allowed to be empty
1367
1368 // unflipped a vs flipped (empty) b yields a
1369 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1370 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1371 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1372
1373 // flipped (empty) a vs unflipped b yields b
1374 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1375 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1376 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1377
1378 // flipped (empty) a vs flipped (empty) b yields empty
1379 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1380 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1381 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1382 };
1383
1384 auto test = [&check_nans, &check_empty_flips](const Rect& a, const Rect& b,
1385 const Rect& result) {
1386 ASSERT_FALSE(a.IsEmpty()) << a;
1387 // b is allowed to be empty
1388
1389 std::stringstream stream;
1390 stream << a << " union " << b;
1391 auto label = stream.str();
1392
1393 EXPECT_EQ(a.Union(b), result) << label;
1394 EXPECT_EQ(b.Union(a), result) << label;
1395 check_empty_flips(a, b, label);
1396 check_nans(a, b, label);
1397 };
1398
1399 {
1400 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1401 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1402 auto expected = Rect::MakeXYWH(100, 100, 100, 100);
1403 test(a, b, expected);
1404 }
1405
1406 {
1407 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1408 auto b = Rect::MakeXYWH(0, 0, 1, 1);
1409 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1410 test(a, b, expected);
1411 }
1412
1413 {
1414 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1415 auto b = Rect::MakeXYWH(10, 10, 1, 1);
1416 auto expected = Rect::MakeXYWH(10, 10, 190, 190);
1417 test(a, b, expected);
1418 }
1419
1420 {
1421 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1422 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1423 auto expected = Rect::MakeXYWH(0, 0, 110, 110);
1424 test(a, b, expected);
1425 }
1426
1427 {
1428 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1429 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1430 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1431 test(a, b, expected);
1432 }
1433 }

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() [304/389]

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

Definition at line 1158 of file rect_unittests.cc.

1158 {
1159 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1160
1161 // Non-empty
1162 EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
1163
1164 // Empty both width and height both 0 or negative, in all combinations
1165 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
1166 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
1167 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
1168 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
1169
1170 // Empty for 0 or negative width or height (but not both at the same time)
1171 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
1172 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
1173 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
1174 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
1175
1176 // Empty for NaN in width or height or both
1177 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
1178 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
1179 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
1180 }

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

## ◆ TEST() [305/389]

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

Definition at line 3110 of file rect_unittests.cc.

3110 {
3111 {
3112 // This matrix should clip no corners.
3113 auto matrix = impeller::Matrix::MakeColumn(
3114 // clang-format off
3115 2.0f, 0.0f, 0.0f, 0.0f,
3116 0.0f, 4.0f, 0.0f, 0.0f,
3117 0.0f, 0.0f, 1.0f, 0.0f,
3118 0.0f, 0.0f, 0.0f, 8.0f
3119 // clang-format on
3120 );
3121 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3122 // None of these should have a W<0
3123 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftTop()),
3124 Vector3(200.0f, 400.0f, 8.0f));
3125 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightTop()),
3126 Vector3(400.0f, 400.0f, 8.0f));
3127 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftBottom()),
3128 Vector3(200.0f, 800.0f, 8.0f));
3129 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightBottom()),
3130 Vector3(400.0f, 800.0f, 8.0f));
3131
3132 Rect expect = Rect::MakeLTRB(25.0f, 50.0f, 50.0f, 100.0f);
3133 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3134 EXPECT_EQ(src.TransformAndClipBounds(matrix), expect);
3135 }
3136
3137 {
3138 // This matrix should clip one corner.
3139 auto matrix = impeller::Matrix::MakeColumn(
3140 // clang-format off
3141 2.0f, 0.0f, 0.0f, -0.01f,
3142 0.0f, 2.0f, 0.0f, -0.006f,
3143 0.0f, 0.0f, 1.0f, 0.0f,
3144 0.0f, 0.0f, 0.0f, 3.0f
3145 // clang-format on
3146 );
3147 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3148 // Exactly one of these should have a W<0
3149 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3150 Vector3(200.0f, 200.0f, 1.4f));
3151 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3152 Vector3(400.0f, 200.0f, 0.4f));
3153 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3154 Vector3(200.0f, 400.0f, 0.8f));
3155 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3156 Vector3(400.0f, 400.0f, -0.2f));
3157
3158 Rect expect = Rect::MakeLTRB(142.85715f, 142.85715f, 6553600.f, 6553600.f);
3159 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3160 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3161 }
3162
3163 {
3164 // This matrix should clip two corners.
3165 auto matrix = impeller::Matrix::MakeColumn(
3166 // clang-format off
3167 2.0f, 0.0f, 0.0f, -.015f,
3168 0.0f, 2.0f, 0.0f, -.006f,
3169 0.0f, 0.0f, 1.0f, 0.0f,
3170 0.0f, 0.0f, 0.0f, 3.0f
3171 // clang-format on
3172 );
3173 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3174 // Exactly two of these should have a W<0
3175 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3176 Vector3(200.0f, 200.0f, 0.9f));
3177 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3178 Vector3(400.0f, 200.0f, -0.6f));
3179 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3180 Vector3(200.0f, 400.0f, 0.3f));
3181 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3182 Vector3(400.0f, 400.0f, -1.2f));
3183
3184 Rect expect = Rect::MakeLTRB(222.2222f, 222.2222f, 5898373.f, 6553600.f);
3185 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3186 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3187 }
3188
3189 {
3190 // This matrix should clip three corners.
3191 auto matrix = impeller::Matrix::MakeColumn(
3192 // clang-format off
3193 2.0f, 0.0f, 0.0f, -.02f,
3194 0.0f, 2.0f, 0.0f, -.006f,
3195 0.0f, 0.0f, 1.0f, 0.0f,
3196 0.0f, 0.0f, 0.0f, 3.0f
3197 // clang-format on
3198 );
3199 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3200 // Exactly three of these should have a W<0
3201 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3202 Vector3(200.0f, 200.0f, 0.4f));
3203 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3204 Vector3(400.0f, 200.0f, -1.6f));
3205 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3206 Vector3(200.0f, 400.0f, -0.2f));
3207 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3208 Vector3(400.0f, 400.0f, -2.2f));
3209
3210 Rect expect = Rect::MakeLTRB(499.99988f, 499.99988f, 5898340.f, 4369400.f);
3211 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3212 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3213 }
3214
3215 {
3216 // This matrix should clip all four corners.
3217 auto matrix = impeller::Matrix::MakeColumn(
3218 // clang-format off
3219 2.0f, 0.0f, 0.0f, -.025f,
3220 0.0f, 2.0f, 0.0f, -.006f,
3221 0.0f, 0.0f, 1.0f, 0.0f,
3222 0.0f, 0.0f, 0.0f, 3.0f
3223 // clang-format on
3224 );
3225 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3226 // All of these should have a W<0
3227 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3228 Vector3(200.0f, 200.0f, -0.1f));
3229 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3230 Vector3(400.0f, 200.0f, -2.6f));
3231 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3232 Vector3(200.0f, 400.0f, -0.7f));
3233 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3234 Vector3(400.0f, 400.0f, -3.2f));
3235
3236 EXPECT_TRUE(src.TransformAndClipBounds(matrix).IsEmpty());
3237 }
3238 }

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() [306/389]

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() [307/389]

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() [308/389]

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() [309/389]

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() [310/389]

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() [311/389]

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() [312/389]

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() [313/389]

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() [314/389]

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() [315/389]

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() [316/389]

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() [317/389]

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() [318/389]

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() [319/389]

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() [320/389]

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() [321/389]

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() [322/389]

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() [323/389]

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() [324/389]

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() [325/389]

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() [326/389]

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() [327/389]

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() [328/389]

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() [329/389]

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() [330/389]

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() [331/389]

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() [332/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | BackdropFilterEmptyCoverage |
| ) |  |

Definition at line 163 of file save_layer_utils_unittests.cc.

163 {
164 // Empty coverage with backdrop filter.
165 auto coverage = ComputeSaveLayerCoverage(
166 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
167 /*effect_transform=*/{}, //
168 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
169 /*image_filter=*/nullptr, //
170 /*flood_output_coverage=*/true //
171 );
172
173 ASSERT_TRUE(coverage.has_value());
174 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
175 }

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

## ◆ TEST() [333/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | BackdropFiterComputedCoverage |
| ) |  |

Definition at line 29 of file save_layer_utils_unittests.cc.

29 {
30 // Backdrop Filter, computed coverage
31 auto coverage = ComputeSaveLayerCoverage(
32 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
33 /*effect_transform=*/{}, //
34 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
35 /*image_filter=*/nullptr,
36 /*flood_output_coverage=*/false, //
37 /*flood_input_coverage=*/true //
38 );
39
40 ASSERT_TRUE(coverage.has_value());
41 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
42 }

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

## ◆ TEST() [334/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | BasicEmptyCoverage |
| ) |  |

Definition at line 137 of file save_layer_utils_unittests.cc.

137 {
138 auto coverage = ComputeSaveLayerCoverage(
139 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
140 /*effect_transform=*/{}, //
141 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
142 /*image_filter=*/nullptr //
143 );
144
145 ASSERT_FALSE(coverage.has_value());
146 }

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

## ◆ TEST() [335/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageLargerWithImageFilter |
| ) |  |

Definition at line 246 of file save_layer_utils_unittests.cc.

248 {
249 // Create an image filter that slightly stretches the coverage limit. Even
250 // without the special logic for using the original content coverage, we
251 // verify that we don't introduce any artifacts from the intersection.
252 auto image_filter = FilterContents::MakeMatrixFilter(
253 FilterInput::Make(Rect()), Matrix::MakeScale({0.9, 0.9, 1}), {});
254
255 auto coverage = ComputeSaveLayerCoverage(
256 /*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
257 /*effect_transform=*/{}, //
258 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
259 /*image_filter=*/image_filter //
260 );
261
262 ASSERT_TRUE(coverage.has_value());
263 // The transfomed coverage limit is ((0, 0), (111.111, 111.111)).
264 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
265 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [336/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageSmallerWithImageFilter |
| ) |  |

Definition at line 227 of file save_layer_utils_unittests.cc.

229 {
230 // Create an image filter that slightly shrinks the coverage limit
231 auto image_filter = FilterContents::MakeMatrixFilter(
232 FilterInput::Make(Rect()), Matrix::MakeScale({1.1, 1.1, 1}), {});
233
234 auto coverage = ComputeSaveLayerCoverage(
235 /*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
236 /*effect_transform=*/{}, //
237 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
238 /*image_filter=*/image_filter //
239 );
240
241 ASSERT_TRUE(coverage.has_value());
242 // The transfomed coverage limit is ((0, 0), (90.9091, 90.9091)).
243 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
244 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [337/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | CoverageLimitRespectedIfSubstantiallyDifferentFromContentCoverge |
| ) |  |

Definition at line 267 of file save_layer_utils_unittests.cc.

268 {
269 auto image_filter = FilterContents::MakeMatrixFilter(
270 FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
271
272 auto coverage = ComputeSaveLayerCoverage(
273 /*content_coverage=*/Rect::MakeLTRB(0, 0, 1000, 1000), //
274 /*effect_transform=*/{}, //
275 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
276 /*image_filter=*/image_filter //
277 );
278
279 ASSERT_TRUE(coverage.has_value());
280 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
281 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [338/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DisjointCoverage |
| ) |  |

Definition at line 94 of file save_layer_utils_unittests.cc.

94 {
95 // No intersection in coverage
96 auto coverage = ComputeSaveLayerCoverage(
97 /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
98 /*effect_transform=*/{}, //
99 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
100 /*image_filter=*/nullptr //
101 );
102
103 EXPECT_FALSE(coverage.has_value());
104 }

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

## ◆ TEST() [339/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DisjointCoverageTransformedByImageFilter |
| ) |  |

Definition at line 106 of file save_layer_utils_unittests.cc.

106 {
107 // Coverage disjoint from parent coverage but transformed into parent space
108 // with image filter.
109 auto image_filter = FilterContents::MakeMatrixFilter(
110 FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
111
112 auto coverage = ComputeSaveLayerCoverage(
113 /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
114 /*effect_transform=*/{}, //
115 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
116 /*image_filter=*/image_filter //
117 );
118
119 ASSERT_TRUE(coverage.has_value());
120 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(200, 200, 210, 210));
121 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [340/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DisjointCoveragTransformedByCTM |
| ) |  |

Definition at line 123 of file save_layer_utils_unittests.cc.

123 {
124 // Coverage disjoint from parent coverage.
125 Matrix ctm = Matrix::MakeTranslation({-200, -200, 0});
126 auto coverage = ComputeSaveLayerCoverage(
127 /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
128 /*effect_transform=*/ctm, //
129 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
130 /*image_filter=*/nullptr //
131 );
132
133 ASSERT_TRUE(coverage.has_value());
134 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
135 }

References impeller::ComputeSaveLayerCoverage(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [341/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | FloodInputCoverage |
| ) |  |

Definition at line 177 of file save_layer_utils_unittests.cc.

177 {
178 auto coverage = ComputeSaveLayerCoverage(
179 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
180 /*effect_transform=*/{}, //
181 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
182 /*image_filter=*/nullptr, //
183 /*flood_output_coverage=*/false, //
184 /*flood_input_coverage=*/true //
185 );
186
187 ASSERT_TRUE(coverage.has_value());
188 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
189 }

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

## ◆ TEST() [342/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | FloodInputCoverageWithImageFilter |
| ) |  |

Definition at line 191 of file save_layer_utils_unittests.cc.

191 {
192 auto image_filter = FilterContents::MakeMatrixFilter(
193 FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
194
195 auto coverage = ComputeSaveLayerCoverage(
196 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
197 /*effect_transform=*/{}, //
198 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
199 /*image_filter=*/image_filter, //
200 /*flood_output_coverage=*/false, //
201 /*flood_input_coverage=*/true //
202 );
203
204 ASSERT_TRUE(coverage.has_value());
205 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 4800, 3600));
206 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [343/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | FloodInputCoverageWithImageFilterWithNoCoverageProducesNoCoverage |
| ) |  |

Definition at line 208 of file save_layer_utils_unittests.cc.

209 {
210 // Even if we flood the input coverage due to a bdf, we can still cull out the
211 // layer if the image filter results in no coverage.
212 auto image_filter = FilterContents::MakeMatrixFilter(
213 FilterInput::Make(Rect()), Matrix::MakeScale({1, 1, 0}), {});
214
215 auto coverage = ComputeSaveLayerCoverage(
216 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
217 /*effect_transform=*/{}, //
218 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
219 /*image_filter=*/image_filter, //
220 /*flood_output_coverage=*/false, //
221 /*flood_input_coverage=*/true //
222 );
223
224 ASSERT_FALSE(coverage.has_value());
225 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [344/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFilterEmptyCoverage |
| ) |  |

Definition at line 148 of file save_layer_utils_unittests.cc.

148 {
149 // Empty coverage with Image Filter
150 auto image_filter = FilterContents::MakeMatrixFilter(
151 FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
152
153 auto coverage = ComputeSaveLayerCoverage(
154 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
155 /*effect_transform=*/{}, //
156 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
157 /*image_filter=*/image_filter //
158 );
159
160 ASSERT_FALSE(coverage.has_value());
161 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [345/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFiterComputedCoverage |
| ) |  |

Definition at line 44 of file save_layer_utils_unittests.cc.

44 {
45 // Image Filter, computed coverage
46 auto image_filter = FilterContents::MakeMatrixFilter(
47 FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
48
49 auto coverage = ComputeSaveLayerCoverage(
50 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
51 /*effect_transform=*/{}, //
52 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
53 /*image_filter=*/image_filter //
54 );
55
56 ASSERT_TRUE(coverage.has_value());
57 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
58 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [346/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFiterLargeScaleComputedCoverageLargerThanBoundsLimit |
| ) |  |

Definition at line 77 of file save_layer_utils_unittests.cc.

78 {
79 // Image Filter scaling small, computed coverage is larger than bounds limit.
80 auto image_filter = FilterContents::MakeMatrixFilter(
81 FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
82
83 auto coverage = ComputeSaveLayerCoverage(
84 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
85 /*effect_transform=*/{}, //
86 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
87 /*image_filter=*/image_filter //
88 );
89
90 ASSERT_TRUE(coverage.has_value());
91 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
92 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [347/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFiterSmallScaleComputedCoverageLargerThanBoundsLimit |
| ) |  |

Definition at line 60 of file save_layer_utils_unittests.cc.

61 {
62 // Image Filter scaling large, computed coverage is larger than bounds limit.
63 auto image_filter = FilterContents::MakeMatrixFilter(
64 FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
65
66 auto coverage = ComputeSaveLayerCoverage(
67 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
68 /*effect_transform=*/{}, //
69 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
70 /*image_filter=*/image_filter //
71 );
72
73 ASSERT_TRUE(coverage.has_value());
74 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2.5, 2.5));
75 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [348/389]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | SimplePaintComputedCoverage |
| ) |  |

Definition at line 17 of file save_layer_utils_unittests.cc.

17 {
18 // Basic Case, simple paint, computed coverage
19 auto coverage = ComputeSaveLayerCoverage(
20 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
21 /*effect_transform=*/{}, //
22 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
23 /*image_filter=*/nullptr //
24 );
25 ASSERT_TRUE(coverage.has_value());
26 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
27 }

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

## ◆ TEST() [349/389]

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() [350/389]

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() [351/389]

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() [352/389]

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() [353/389]

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() [354/389]

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() [355/389]

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

Definition at line 297 of file skia_conversions_unittests.cc.

297 {
298 for (auto i = 0; i < static_cast<int>(flutter::DlBlendMode::kLastMode); i++) {
299 EXPECT_EQ(
300 skia_conversions::ToBlendMode(static_cast<flutter::DlBlendMode>(i)),
301 static_cast<BlendMode>(i));
302 }
303 }

References impeller::skia_conversions::ToBlendMode().

## ◆ TEST() [356/389]

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

Definition at line 234 of file skia_conversions_unittests.cc.

234 {
235 std::vector<flutter::DlColor> colors = {
236 flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
237 flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
238 std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
239 const auto gradient =
240 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
241 SkPoint::Make(1.0, 1.0), //
242 4, //
243 colors.data(), //
244 stops.data(), //
245 flutter::DlTileMode::kClamp, //
246 nullptr //
247 );
248
249 std::vector<Color> converted_colors;
250 std::vector<Scalar> converted_stops;
251 skia_conversions::ConvertStops(gradient.get(), converted_colors,
252 converted_stops);
253
254 // Value is clamped to 0.5
255 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
256 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
257 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
258 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
259 }

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

## ◆ TEST() [357/389]

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

Definition at line 156 of file skia_conversions_unittests.cc.

156 {
157 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
158 flutter::DlColor::kRed()};
159 std::vector<float> stops = {0.5, 1.0};
160 const auto gradient =
161 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
162 SkPoint::Make(1.0, 1.0), //
163 2, //
164 colors.data(), //
165 stops.data(), //
166 flutter::DlTileMode::kClamp, //
167 nullptr //
168 );
169
170 std::vector<Color> converted_colors;
171 std::vector<Scalar> converted_stops;
172 skia_conversions::ConvertStops(gradient.get(), converted_colors,
173 converted_stops);
174
175 // First color is inserted as blue.
176 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
177 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
178 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
179 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
180 }

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

## ◆ TEST() [358/389]

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

Definition at line 182 of file skia_conversions_unittests.cc.

182 {
183 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
184 flutter::DlColor::kRed()};
185 std::vector<float> stops = {0.0, .5};
186 const auto gradient =
187 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
188 SkPoint::Make(1.0, 1.0), //
189 2, //
190 colors.data(), //
191 stops.data(), //
192 flutter::DlTileMode::kClamp, //
193 nullptr //
194 );
195
196 std::vector<Color> converted_colors;
197 std::vector<Scalar> converted_stops;
198 skia_conversions::ConvertStops(gradient.get(), converted_colors,
199 converted_stops);
200
201 // Last color is inserted as red.
202 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
203 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
204 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
205 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
206 }

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

## ◆ TEST() [359/389]

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

Definition at line 130 of file skia_conversions_unittests.cc.

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

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

## ◆ TEST() [360/389]

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

Definition at line 208 of file skia_conversions_unittests.cc.

208 {
209 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
210 flutter::DlColor::kGreen(),
211 flutter::DlColor::kRed()};
212 std::vector<float> stops = {0.0, 100, 1.0};
213 const auto gradient =
214 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
215 SkPoint::Make(1.0, 1.0), //
216 3, //
217 colors.data(), //
218 stops.data(), //
219 flutter::DlTileMode::kClamp, //
220 nullptr //
221 );
222
223 std::vector<Color> converted_colors;
224 std::vector<Scalar> converted_stops;
225 skia_conversions::ConvertStops(gradient.get(), converted_colors,
226 converted_stops);
227
228 // Value is clamped to 1.0
229 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
230 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
231 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
232 }

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

## ◆ TEST() [361/389]

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

Definition at line 261 of file skia_conversions_unittests.cc.

261 {
262 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
263 SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 10)));
264 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
265 SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9.999)));
266 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
267 SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9)));
268 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
269 SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 5)));
270 SkRect rect = SkRect::MakeLTRB(0, 0, 10, 10);
271 SkRRect rrect;
272 union {
273 SkPoint radii[4] = {
274 {10.0f, 9.0f},
275 {10.0f, 9.0f},
276 {10.0f, 9.0f},
277 {10.0f, 9.0f},
278 };
279 SkScalar values[8];
280 } test;
281 rrect.setRectRadii(rect, test.radii);
282 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect));
283 for (int i = 0; i < 8; i++) {
284 auto save = test.values[i];
285 test.values[i] -= kEhCloseEnough * 0.5f;
286 rrect.setRectRadii(rect, test.radii);
287 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect))
288 << "values[" << i << "] == " << test.values[i];
289 test.values[i] -= kEhCloseEnough * 2.0f;
290 rrect.setRectRadii(rect, test.radii);
291 EXPECT_FALSE(skia_conversions::IsNearlySimpleRRect(rrect))
292 << "values[" << i << "] == " << test.values[i];
293 test.values[i] = save;
294 }
295 }

References impeller::skia_conversions::IsNearlySimpleRRect(), and impeller::kEhCloseEnough.

## ◆ TEST() [362/389]

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

Definition at line 98 of file skia_conversions_unittests.cc.

98 {
99 for (int x = -100; x < 100; x += 4) {
100 for (int y = -100; y < 100; y += 4) {
101 EXPECT_EQ(skia_conversions::ToPoint(SkPoint::Make(x * 0.25f, y * 0.25f)),
102 Point(x * 0.25f, y * 0.25f));
103 }
104 }
105 }

References impeller::skia_conversions::ToPoint().

## ◆ TEST() [363/389]

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

Definition at line 107 of file skia_conversions_unittests.cc.

107 {
108 for (int x = -100; x < 100; x += 4) {
109 for (int y = -100; y < 100; y += 4) {
110 EXPECT_EQ(skia_conversions::ToSize(SkPoint::Make(x * 0.25f, y * 0.25f)),
111 Size(x * 0.25f, y * 0.25f));
112 }
113 }
114 }

References impeller::skia_conversions::ToSize().

## ◆ TEST() [364/389]

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

Definition at line 116 of file skia_conversions_unittests.cc.

116 {
117 // Create a color with alpha, red, green, and blue values that are all
118 // trivially divisible by 255 so that we can test the conversion results in
119 // correct scalar values.
120 // AARRGGBB
121 const flutter::DlColor color = flutter::DlColor(0x8040C020);
122 auto converted_color = skia_conversions::ToColor(color);
123
124 ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
125 ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
126 ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
127 ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
128 }

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

## ◆ TEST() [365/389]

impeller::testing::TEST | ( | SkiaConversionTest | ,
|  | ToMatrixRotate |
| ) |  |

Definition at line 47 of file skia_conversions_unittests.cc.

47 {
48 SkMatrix sk_matrix = SkMatrix::RotateDeg(90);
49 Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
50
51 EXPECT_EQ(matrix.vec[0], Vector4(0, 1, 0, 0));
52 EXPECT_EQ(matrix.vec[1], Vector4(-1, 0, 0, 0));
53 EXPECT_EQ(matrix.vec[2], Vector4(0, 0, 1, 0));
54 EXPECT_EQ(matrix.vec[3], Vector4(0, 0, 0, 1));
55 EXPECT_FALSE(matrix.IsTranslationScaleOnly());
56 }

References impeller::Matrix::IsTranslationScaleOnly(), impeller::skia_conversions::ToMatrix(), and impeller::Matrix::vec.

## ◆ TEST() [366/389]

impeller::testing::TEST | ( | SkiaConversionTest | ,
|  | ToMatrixScale |
| ) |  |

Definition at line 33 of file skia_conversions_unittests.cc.

33 {
34 SkMatrix sk_matrix = SkMatrix::Scale(2, 2);
35 Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
36
37 EXPECT_EQ(matrix.m[0], 2);
38 EXPECT_EQ(matrix.m[5], 2);
39 EXPECT_TRUE(matrix.IsTranslationScaleOnly());
40
41 matrix.m[0] = 1;
42 matrix.m[5] = 1;
43
44 EXPECT_TRUE(matrix.IsIdentity());
45 }

References impeller::Matrix::IsIdentity(), impeller::Matrix::IsTranslationScaleOnly(), impeller::Matrix::m, and impeller::skia_conversions::ToMatrix().

## ◆ TEST() [367/389]

impeller::testing::TEST | ( | SkiaConversionTest | ,
|  | ToMatrixSkew |
| ) |  |

Definition at line 58 of file skia_conversions_unittests.cc.

58 {
59 SkMatrix sk_matrix = SkMatrix::Skew(2, 2);
60 Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
61
62 EXPECT_EQ(matrix.vec[0], Vector4(1, 2, 0, 0));
63 EXPECT_EQ(matrix.vec[1], Vector4(2, 1, 0, 0));
64 EXPECT_EQ(matrix.vec[2], Vector4(0, 0, 1, 0));
65 EXPECT_EQ(matrix.vec[3], Vector4(0, 0, 0, 1));
66 EXPECT_FALSE(matrix.IsTranslationScaleOnly());
67 }

References impeller::Matrix::IsTranslationScaleOnly(), impeller::skia_conversions::ToMatrix(), and impeller::Matrix::vec.

## ◆ TEST() [368/389]

impeller::testing::TEST | ( | SkiaConversionTest | ,
|  | ToMatrixTranslate |
| ) |  |

Definition at line 19 of file skia_conversions_unittests.cc.

19 {
20 SkMatrix sk_matrix = SkMatrix::Translate(100, 100);
21 Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
22
23 EXPECT_EQ(matrix.m[12], 100);
24 EXPECT_EQ(matrix.m[13], 100);
25 EXPECT_TRUE(matrix.IsTranslationScaleOnly());
26
27 matrix.m[12] = 0;
28 matrix.m[13] = 0;
29
30 EXPECT_TRUE(matrix.IsIdentity());
31 }

References impeller::Matrix::IsIdentity(), impeller::Matrix::IsTranslationScaleOnly(), impeller::Matrix::m, and impeller::skia_conversions::ToMatrix().

## ◆ TEST() [369/389]

impeller::testing::TEST | ( | SkiaConversionTest | ,
|  | ToSamplerDescriptor |
| ) |  |

Definition at line 69 of file skia_conversions_unittests.cc.

69 {
70 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
71 flutter::DlImageSampling::kNearestNeighbor)
72 .min_filter,
73 impeller::MinMagFilter::kNearest);
74 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
75 flutter::DlImageSampling::kNearestNeighbor)
76 .mip_filter,
77 impeller::MipFilter::kBase);
78
79 EXPECT_EQ(
80 skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
81 .min_filter,
82 impeller::MinMagFilter::kLinear);
83 EXPECT_EQ(
84 skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
85 .mip_filter,
86 impeller::MipFilter::kBase);
87
88 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
89 flutter::DlImageSampling::kMipmapLinear)
90 .min_filter,
91 impeller::MinMagFilter::kLinear);
92 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
93 flutter::DlImageSampling::kMipmapLinear)
94 .mip_filter,
95 impeller::MipFilter::kLinear);
96 }

References impeller::kBase, impeller::kLinear, impeller::kNearest, and impeller::skia_conversions::ToSamplerDescriptor().

## ◆ TEST() [370/389]

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

Definition at line 84 of file base_unittests.cc.

84 {
85 ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
86 ASSERT_EQ(SPrintF(""), "");
87 ASSERT_EQ(SPrintF("Hello"), "Hello");
88 ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
89 }

References impeller::SPrintF().

## ◆ TEST() [371/389]

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() [372/389]

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() [373/389]

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() [374/389]

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() [375/389]

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() [376/389]

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() [377/389]

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() [378/389]

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() [379/389]

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() [380/389]

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() [381/389]

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() [382/389]

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() [383/389]

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() [384/389]

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() [385/389]

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 [[maybe_unused]] int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
63 f.mtx.UnlockReader();
64 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [386/389]

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

Definition at line 66 of file base_unittests.cc.

66 {
67 RWFoo f = {};
68
69 // f.a = 100; <--- Static analysis error.
70 {
71 auto write_lock = WriterLock{f.mtx};
72 f.a = 100;
73 }
74
75 // int b = f.a; <--- Static analysis error.
76 {
77 auto read_lock = ReaderLock(f.mtx);
78 [[maybe_unused]] int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
79 }
80
81 // f.mtx.UnlockReader(); <--- Static analysis error.
82 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [387/389]

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() [388/389]

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

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 76 of file golden_tests.cc.

76 {
77 flutter::DisplayListBuilder builder;
78 flutter::DlPaint paint;
79 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
80
81 flutter::DlColor colors[2] = {flutter::DlColor::RGBA(1, 0, 0, 1),
82 flutter::DlColor::RGBA(0, 0, 1, 1)};
83 Scalar stops[2] = {0, 1};
84
85 paint.setColorSource(flutter::DlConicalGradientColorSource::MakeConical(
86 /*start_center=*/{125, 125}, //
87 /*start_radius=*/125, {180, 180}, //
88 /*end_radius=*/0, //
89 /*stop_count=*/2, //
90 /*colors=*/colors, //
91 /*stops=*/stops, //
92 /*tile_mode=*/flutter::DlTileMode::kClamp //
93 ));
94
95 builder.DrawRect(SkRect::MakeXYWH(10, 10, 250, 250), paint);
96
97 auto aiks_context =
98 AiksContext(Screenshotter().GetPlayground().GetContext(), nullptr);
99 auto screenshot = Screenshotter().MakeScreenshot(
100 aiks_context,
101 DisplayListToTexture(builder.Build(), {240, 240}, aiks_context));
102 ASSERT_TRUE(SaveScreenshot(std::move(screenshot)));
103 }

References impeller::DisplayListToTexture(), and impeller::testing::Screenshotter::MakeScreenshot().

## ◆ TEST_P() [1/454]

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

Definition at line 429 of file aiks_dl_path_unittests.cc.

429 {
430 DisplayListBuilder builder;
431 builder.Scale(GetContentScale().x, GetContentScale().y);
432
433 DlPaint paint;
434 paint.setColor(DlColor::kRed());
435
436 std::vector<DlColor> colors = {DlColor::RGBA(1.0, 0.0, 0.0, 1.0),
437 DlColor::RGBA(0.0, 0.0, 0.0, 1.0)};
438 std::vector<Scalar> stops = {0.0, 1.0};
439
440 paint.setColorSource(
441 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
442 stops.data(), DlTileMode::kMirror));
443 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
444
445 SkPath path;
446 path.addArc(SkRect::MakeXYWH(10, 10, 100, 100), 0, 0);
447 builder.DrawPath(path, paint);
448
449 // Check that this empty picture can be created without crashing.
450 builder.Build();
451 }

## ◆ TEST_P() [2/454]

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

Definition at line 895 of file aiks_dl_unittests.cc.

895 {
896 DisplayListBuilder builder;
897
898 DlPaint paint;
899 // Add a difference clip that cuts out the bottom right corner
900 builder.ClipRect(SkRect::MakeLTRB(50, 50, 100, 100),
901 DlCanvas::ClipOp::kDifference);
902
903 // Draw a red rectangle that's going to be completely covered by green later.
904 paint.setColor(DlColor::kRed());
905 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
906
907 // Add a clip restricting the backdrop filter to the top right corner.
908 auto count = builder.GetSaveCount();
909 builder.Save();
910 {
911 builder.ClipRect(SkRect::MakeLTRB(0, 0, 100, 100));
912 {
913 // Create a save layer with a backdrop blur filter.
914 auto backdrop_filter =
915 DlBlurImageFilter::Make(10.0, 10.0, DlTileMode::kDecal);
916 builder.SaveLayer(nullptr, nullptr, backdrop_filter.get());
917 }
918 }
919 builder.RestoreToCount(count);
920
921 // Finally, overwrite all the previous stuff with green.
922 paint.setColor(DlColor::kGreen());
923 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
924
925 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
926 }

## ◆ TEST_P() [3/454]

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

Definition at line 432 of file aiks_dl_blend_unittests.cc.

432 {
433 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
434 PixelFormat::kB10G10R10A10XR);
435 auto texture = CreateTextureForFixture("airplane.jpg",
436 /*enable_mipmapping=*/true);
437
438 DisplayListBuilder builder;
439 builder.Scale(GetContentScale().x, GetContentScale().y);
440
441 DlPaint paint;
442 paint.setColor(DlColor::RGBA(0.1, 0.2, 0.1, 1.0));
443 builder.DrawPaint(paint);
444
445 DlPaint save_paint;
446 save_paint.setColorFilter(
447 DlBlendColorFilter::Make(DlColor::RGBA(1, 0, 0, 1), DlBlendMode::kPlus));
448 builder.SaveLayer(nullptr, &save_paint);
449
450 paint.setColor(DlColor::kRed());
451 builder.DrawRect(SkRect::MakeXYWH(100, 100, 400, 400), paint);
452
453 paint.setColor(DlColor::kWhite());
454
455 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
456 builder.DrawImageRect(
457 DlImageImpeller::Make(texture),
458 SkRect::MakeSize(
459 SkSize::Make(texture->GetSize().width, texture->GetSize().height)),
460 SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(),
461 rect.GetBottom()),
462 DlImageSampling::kMipmapLinear, &paint);
463 builder.Restore();
464
465 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
466 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [4/454]

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

Definition at line 399 of file aiks_dl_blend_unittests.cc.

399 {
400 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
401 PixelFormat::kB10G10R10A10XR);
402 auto texture = CreateTextureForFixture("airplane.jpg",
403 /*enable_mipmapping=*/true);
404
405 DisplayListBuilder builder;
406 DlPaint paint;
407 builder.Scale(GetContentScale().x, GetContentScale().y);
408
409 paint.setColor(DlColor::RGBA(0.9, 1, 0.9, 1.0));
410 builder.DrawPaint(paint);
411 builder.SaveLayer(nullptr);
412
413 paint.setBlendMode(DlBlendMode::kPlus);
414 paint.setColor(DlColor::kRed());
415
416 builder.DrawRect(SkRect::MakeXYWH(100, 100, 400, 400), paint);
417 paint.setColor(DlColor::kWhite());
418
419 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
420 builder.DrawImageRect(
421 DlImageImpeller::Make(texture),
422 SkRect::MakeSize(
423 SkSize::Make(texture->GetSize().width, texture->GetSize().height)),
424 SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(),
425 rect.GetBottom()),
426 DlImageSampling::kMipmapLinear, &paint);
427 builder.Restore();
428 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
429 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [5/454]

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

Definition at line 83 of file aiks_dl_blend_unittests.cc.

83 {
84 DisplayListBuilder builder;
85 DlPaint paint;
86
87 paint.setColor(DlColor::kRed());
88 builder.DrawPaint(paint);
89
90 paint.setBlendMode(DlBlendMode::kSrcOver);
91 builder.SaveLayer(nullptr, &paint);
92
93 paint.setColor(DlColor::kWhite());
94 builder.DrawRect(SkRect::MakeXYWH(100, 100, 400, 400), paint);
95
96 paint.setBlendMode(DlBlendMode::kSrc);
97 builder.SaveLayer(nullptr, &paint);
98
99 paint.setColor(DlColor::kBlue());
100 builder.DrawRect(SkRect::MakeXYWH(200, 200, 200, 200), paint);
101
102 builder.Restore();
103 builder.Restore();
104
105 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
106 }

## ◆ TEST_P() [6/454]

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

Definition at line 358 of file aiks_dl_blur_unittests.cc.

358 {
359 Scalar sigma = 47.6;
360 auto callback = [&]() -> sk_sp<DisplayList> {
361 if (AiksTest::ImGuiBegin("Controls", nullptr,
362 ImGuiWindowFlags_AlwaysAutoResize)) {
363 ImGui::SliderFloat("Sigma", &sigma, 0, 50);
364 ImGui::End();
365 }
366 DisplayListBuilder builder;
367 builder.Scale(GetContentScale().x, GetContentScale().y);
368 builder.DrawPaint({});
369
370 DlPaint paint;
371 paint.setColor(DlColor::kGreen());
372 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
373
374 builder.DrawRect(SkRect::MakeXYWH(300, 300, 200, 200), paint);
375 return builder.Build();
376 };
377
378 ASSERT_TRUE(OpenPlaygroundHere(callback));
379 }

References impeller::AiksPlayground::ImGuiBegin().

## ◆ TEST_P() [7/454]

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

Definition at line 1096 of file aiks_dl_blur_unittests.cc.

1096 {
1097 DisplayListBuilder builder;
1098 builder.Scale(GetContentScale().x, GetContentScale().y);
1099
1100 auto paint_lines = [&builder](Scalar dx, Scalar dy, DlPaint paint) {
1101 auto draw_line = [&builder, &paint](SkPoint a, SkPoint b) {
1102 SkPath line = SkPath::Line(a, b);
1103 builder.DrawPath(line, paint);
1104 };
1105 paint.setStrokeWidth(5);
1106 paint.setDrawStyle(DlDrawStyle::kStroke);
1107 draw_line(SkPoint::Make(dx + 100, dy + 100),
1108 SkPoint::Make(dx + 200, dy + 200));
1109 draw_line(SkPoint::Make(dx + 100, dy + 200),
1110 SkPoint::Make(dx + 200, dy + 100));
1111 draw_line(SkPoint::Make(dx + 150, dy + 100),
1112 SkPoint::Make(dx + 200, dy + 150));
1113 draw_line(SkPoint::Make(dx + 100, dy + 150),
1114 SkPoint::Make(dx + 150, dy + 200));
1115 };
1116
1117 AiksContext renderer(GetContext(), nullptr);
1118 DisplayListBuilder recorder_builder;
1119 for (int x = 0; x < 5; ++x) {
1120 for (int y = 0; y < 5; ++y) {
1121 SkRect rect = SkRect::MakeXYWH(x * 20, y * 20, 20, 20);
1122 DlPaint paint;
1123 paint.setColor(((x + y) & 1) == 0 ? DlColor::kYellow()
1124 : DlColor::kBlue());
1125
1126 recorder_builder.DrawRect(rect, paint);
1127 }
1128 }
1129 auto texture =
1130 DisplayListToTexture(recorder_builder.Build(), {100, 100}, renderer);
1131
1132 auto image_source = std::make_shared<DlImageColorSource>(
1133 DlImageImpeller::Make(texture), DlTileMode::kRepeat, DlTileMode::kRepeat);
1134 auto blur_filter = DlBlurImageFilter::Make(5, 5, DlTileMode::kDecal);
1135
1136 DlPaint paint;
1137 paint.setColor(DlColor::kDarkGreen());
1138 builder.DrawRect(SkRect::MakeLTRB(0, 0, 300, 600), paint);
1139
1140 paint.setColorSource(image_source);
1141 builder.DrawRect(SkRect::MakeLTRB(100, 100, 200, 200), paint);
1142
1143 paint.setColorSource(nullptr);
1144 paint.setColor(DlColor::kRed());
1145 builder.DrawRect(SkRect::MakeLTRB(300, 0, 600, 600), paint);
1146
1147 paint.setColorSource(image_source);
1148 paint.setImageFilter(blur_filter);
1149 builder.DrawRect(SkRect::MakeLTRB(400, 100, 500, 200), paint);
1150
1151 paint.setImageFilter(nullptr);
1152 paint_lines(0, 300, paint);
1153
1154 paint.setImageFilter(blur_filter);
1155 paint_lines(300, 300, paint);
1156
1157 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1158 }

References impeller::saturated::b, impeller::DisplayListToTexture(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [8/454]

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

Definition at line 154 of file aiks_dl_vertices_unittests.cc.

154 {
155 constexpr Scalar hexagon_radius = 125;
156 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
157 auto center_to_flat = 1.73 / 2 * hexagon_radius;
158
159 // clang-format off
160 std::vector<SkPoint> vertices = {
161 SkPoint::Make(hex_start.x, hex_start.y),
162 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 0.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 + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
165 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
166 SkPoint::Make(hex_start.x, hex_start.y + 2 * 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 + 1.5 * hexagon_radius),
169 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
170 };
171 // clang-format on
172 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
173 auto dl_vertices = flutter::DlVertices::Make(
174 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
175 nullptr, nullptr);
176 flutter::DisplayListBuilder builder;
177 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
178 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
179 }

## ◆ TEST_P() [9/454]

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

Definition at line 181 of file aiks_dl_path_unittests.cc.

181 {
182 DisplayListBuilder builder;
183
184 // Starting at (50, 50), draw lines from:
185 // 1. (50, height)
186 // 2. (width, height)
187 // 3. (width, 50)
188 SkPath path;
189 path.moveTo(50, 50);
190 path.lineTo(50, 100);
191 path.lineTo(100, 100);
192 path.lineTo(100, 50);
193
194 DlPaint paint;
195 paint.setColor(DlColor::kRed());
196 paint.setDrawStyle(DlDrawStyle::kStroke);
197 paint.setStrokeWidth(10);
198
199 builder.DrawPath(path, paint);
200
201 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
202 }

## ◆ TEST_P() [10/454]

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

Definition at line 204 of file aiks_dl_path_unittests.cc.

204 {
205 DisplayListBuilder builder;
206
207 // Draw a stroked path that is explicitly closed to verify
208 // It doesn't become a rectangle.
209 SkPath path;
210 // PathBuilder builder;
211 path.moveTo(50, 50);
212 path.lineTo(520, 120);
213 path.lineTo(300, 310);
214 path.lineTo(100, 50);
215 path.close();
216
217 DlPaint paint;
218 paint.setColor(DlColor::kRed());
219 paint.setDrawStyle(DlDrawStyle::kStroke);
220 paint.setStrokeWidth(10);
221
222 builder.DrawPath(path, paint);
223
224 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
225 }

## ◆ TEST_P() [11/454]

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

Definition at line 407 of file aiks_dl_path_unittests.cc.

407 {
408 SkPath path;
409 for (auto i = 0; i < 10; i++) {
410 if (i % 2 == 0) {
411 path.addCircle(100 + 50 * i, 100 + 50 * i, 100);
412 path.close();
413 } else {
414 path.moveTo({100.f + 50.f * i - 100, 100.f + 50.f * i});
415 path.lineTo({100.f + 50.f * i, 100.f + 50.f * i - 100});
416 path.lineTo({100.f + 50.f * i - 100, 100.f + 50.f * i - 100});
417 path.close();
418 }
419 }
420
421 DisplayListBuilder builder;
422 DlPaint paint;
423 paint.setColor(DlColor::kRed().withAlpha(102));
424 builder.DrawPath(path, paint);
425
426 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
427 }

## ◆ TEST_P() [12/454]

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

Definition at line 392 of file aiks_dl_basic_unittests.cc.

392 {
393 auto medium_turquoise =
394 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
395
396 DisplayListBuilder builder;
397 builder.Scale(0.2, 0.2);
398 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
399 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
400 }

## ◆ TEST_P() [13/454]

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

Definition at line 402 of file aiks_dl_basic_unittests.cc.

402 {
403 auto medium_turquoise =
404 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
405 auto orange_red =
406 DlColor::RGBA(255.0f / 255.0f, 69.0f / 255.0f, 0.0f / 255.0f, 1.0f);
407
408 DisplayListBuilder builder;
409 builder.Scale(0.2, 0.2);
410 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
411 builder.DrawPaint(DlPaint().setColor(orange_red.modulateOpacity(0.5f)));
412 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
413 }

## ◆ TEST_P() [14/454]

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

Definition at line 683 of file aiks_dl_blend_unittests.cc.

683 {
684 auto modes = GetBlendModeSelection();
685
686 auto callback = [&]() -> sk_sp<DisplayList> {
687 static Color background = Color::MediumTurquoise();
688 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
689 static int current_blend_index = 3;
690
691 if (AiksTest::ImGuiBegin("Controls", nullptr,
692 ImGuiWindowFlags_AlwaysAutoResize)) {
693 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
694 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
695 ImGui::ListBox("Blend mode", &current_blend_index,
696 modes.blend_mode_names.data(),
697 modes.blend_mode_names.size());
698 ImGui::End();
699 }
700
701 DisplayListBuilder builder;
702 builder.Scale(0.2, 0.2);
703 DlPaint paint;
704 paint.setColor(DlColor(background.ToARGB()));
705 builder.DrawPaint(paint);
706
707 paint.setColor(DlColor(foreground.ToARGB()));
708 paint.setBlendMode(static_cast<DlBlendMode>(current_blend_index));
709 builder.DrawPaint(paint);
710 return builder.Build();
711 };
712 ASSERT_TRUE(OpenPlaygroundHere(callback));
713 }

References GetBlendModeSelection(), impeller::AiksPlayground::ImGuiBegin(), impeller::Color::MediumTurquoise(), impeller::Color::ToARGB(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [15/454]

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

Definition at line 108 of file aiks_dl_blend_unittests.cc.

108 {
109 DisplayListBuilder builder;
110
111 builder.Scale(0.2, 0.2);
112 DlPaint paint;
113 paint.setColor(DlColor::RGBA(
114 Color::MediumTurquoise().red, Color::MediumTurquoise().green,
115 Color::MediumTurquoise().blue, Color::MediumTurquoise().alpha));
116 builder.DrawPaint(paint);
117
118 paint.setColor(DlColor::RGBA(Color::OrangeRed().red, Color::OrangeRed().green,
119 Color::OrangeRed().blue, 0.5));
120 paint.setBlendMode(DlBlendMode::kHue);
121 builder.DrawPaint(paint);
122
123 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
124 }

References impeller::Color::MediumTurquoise(), and impeller::Color::OrangeRed().

## ◆ TEST_P() [16/454]

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

Definition at line 825 of file aiks_dl_basic_unittests.cc.

825 {
826 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
827 int time = 0;
828 auto callback = [&]() -> sk_sp<DisplayList> {
829 DisplayListBuilder builder;
830
831 builder.Save();
832 {
833 builder.Translate(300, 300);
834
835 // 1. Draw/restore a clip before drawing the image, which will get drawn
836 // to the depth buffer behind the image.
837 builder.Save();
838 {
839 DlPaint paint;
840 paint.setColor(DlColor::kGreen());
841 builder.DrawPaint(paint);
842 builder.ClipRect(SkRect::MakeLTRB(-180, -180, 180, 180),
843 DlCanvas::ClipOp::kDifference);
844
845 paint.setColor(DlColor::kBlack());
846 builder.DrawPaint(paint);
847 }
848 builder.Restore(); // Restore rectangle difference clip.
849
850 builder.Save();
851 {
852 // 2. Draw an oval clip that applies to the image, which will get drawn
853 // in front of the image on the depth buffer.
854 builder.ClipOval(SkRect::MakeLTRB(-200, -200, 200, 200));
855
856 Matrix result =
857 Matrix(1.0, 0.0, 0.0, 0.0, //
858 0.0, 1.0, 0.0, 0.0, //
859 0.0, 0.0, 1.0, 0.003, //
860 0.0, 0.0, 0.0, 1.0) *
861 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
862
863 // 3. Draw the rotating image with a perspective transform.
864 builder.Transform(FromImpellerMatrix(result));
865
866 auto image =
867 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
868 auto position = -SkPoint::Make(image->dimensions().fWidth,
869 image->dimensions().fHeight) *
870 0.5;
871 builder.DrawImage(image, position, {});
872 }
873 builder.Restore(); // Restore oval intersect clip.
874
875 // 4. Draw a semi-translucent blue circle atop all previous draws.
876 DlPaint paint;
877 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
878 builder.DrawCircle({}, 230, paint);
879 }
880 builder.Restore(); // Restore translation.
881
882 return builder.Build();
883 };
884 ASSERT_TRUE(OpenPlaygroundHere(callback));
885 }

References impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRotationY(), and impeller::Matrix::Transform().

## ◆ TEST_P() [17/454]

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

Definition at line 396 of file aiks_dl_unittests.cc.

396 {
397 std::vector<SkPoint> points = {
398 {0, 0}, //
399 {100, 100}, //
400 {100, 0}, //
401 {0, 100}, //
402 {0, 0}, //
403 {48, 48}, //
404 {52, 52}, //
405 };
406 DlPaint paint_round;
407 paint_round.setColor(DlColor::kYellow().withAlpha(128));
408 paint_round.setStrokeCap(DlStrokeCap::kRound);
409 paint_round.setStrokeWidth(20);
410
411 DlPaint paint_square;
412 paint_square.setColor(DlColor::kYellow().withAlpha(128));
413 paint_square.setStrokeCap(DlStrokeCap::kSquare);
414 paint_square.setStrokeWidth(20);
415
416 DlPaint background;
417 background.setColor(DlColor::kBlack());
418
419 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
420 builder.DrawPaint(background);
421 builder.Translate(200, 200);
422
423 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
424 paint_round);
425 builder.Translate(150, 0);
426 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
427 paint_square);
428
429 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
430 }

## ◆ TEST_P() [18/454]

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

Definition at line 432 of file aiks_dl_unittests.cc.

432 {
433 auto texture = DlImageImpeller::Make(
434 CreateTextureForFixture("table_mountain_nx.png",
435 /*enable_mipmapping=*/true));
436
437 std::vector<SkPoint> points = {
438 {0, 0}, //
439 {100, 100}, //
440 {100, 0}, //
441 {0, 100}, //
442 {0, 0}, //
443 {48, 48}, //
444 {52, 52}, //
445 };
446
447 auto image_src = std::make_shared<DlImageColorSource>(
448 texture, DlTileMode::kClamp, DlTileMode::kClamp);
449
450 DlPaint paint_round;
451 paint_round.setStrokeCap(DlStrokeCap::kRound);
452 paint_round.setColorSource(image_src);
453 paint_round.setStrokeWidth(200);
454
455 DlPaint paint_square;
456 paint_square.setStrokeCap(DlStrokeCap::kSquare);
457 paint_square.setColorSource(image_src);
458 paint_square.setStrokeWidth(200);
459
460 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
461 builder.Translate(200, 200);
462
463 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
464 paint_round);
465 builder.Translate(150, 0);
466 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
467 paint_square);
468
469 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
470 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [19/454]

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

Definition at line 832 of file aiks_dl_unittests.cc.

832 {
833 std::vector<SkPoint> point = {
834 {0, 0}, //
835 };
836
837 DlPaint paint;
838 paint.setStrokeCap(DlStrokeCap::kRound);
839 paint.setColor(DlColor::kRed());
840 paint.setStrokeWidth(100 * 0.000001);
841
842 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
843 builder.Translate(200, 200);
844 builder.Scale(1000000, 1000000);
845
846 builder.DrawPoints(DlCanvas::PointMode::kPoints, point.size(), point.data(),
847 paint);
848 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
849 }

## ◆ TEST_P() [20/454]

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

Definition at line 811 of file aiks_dl_unittests.cc.

811 {
812 std::vector<SkPoint> point = {
813 {0, 0}, //
814 };
815
816 DlPaint paint;
817 paint.setStrokeCap(DlStrokeCap::kRound);
818 paint.setColor(DlColor::kRed());
819 paint.setStrokeWidth(100 * 1000000);
820
821 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
822 builder.Translate(200, 200);
823 builder.Scale(0.000001, 0.000001);
824
825 builder.DrawPoints(DlCanvas::PointMode::kPoints, point.size(), point.data(),
826 paint);
827
828 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
829 }

## ◆ TEST_P() [21/454]

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

Definition at line 955 of file aiks_dl_unittests.cc.

955 {
956 DisplayListBuilder recorder_builder;
957
958 DisplayListBuilder builder;
959 AiksContext renderer(GetContext(), nullptr);
960
961 DlPaint paint;
962 paint.setColor(DlColor::kTransparent());
963 builder.DrawPaint(paint);
964
965 auto result_image =
966 DisplayListToTexture(builder.Build(), ISize{1000, 1000}, renderer);
967 if (result_image) {
968 recorder_builder.DrawImage(DlImageImpeller::Make(result_image), {}, {});
969
970 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
971 recorder_builder.DrawRect(SkRect::MakeSize({1000, 1000}), paint);
972 }
973
974 ASSERT_TRUE(OpenPlaygroundHere(recorder_builder.Build()));
975 }

References impeller::DisplayListToTexture(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [22/454]

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

Definition at line 1150 of file aiks_dl_basic_unittests.cc.

1150 {
1151 DisplayListBuilder builder;
1152
1153 DlPaint paint;
1154 paint.setColor(DlColor::kRed());
1155 builder.DrawCircle(SkPoint::Make(250, 250), 125, paint);
1156
1157 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1158 }

## ◆ TEST_P() [23/454]

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

Definition at line 1171 of file aiks_dl_basic_unittests.cc.

1171 {
1172 DisplayListBuilder builder;
1173
1174 DlPaint save;
1175 save.setColor(DlColor::kBlack());
1176
1177 SkRect save_bounds = SkRect::MakeXYWH(0, 0, 50, 50);
1178 builder.SaveLayer(&save_bounds, &save);
1179
1180 DlPaint paint;
1181 paint.setColor(DlColor::kRed());
1182 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1183 paint.setColor(DlColor::kGreen());
1184 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100), paint);
1185 paint.setColor(DlColor::kBlue());
1186 builder.DrawRect(SkRect::MakeXYWH(20, 20, 100, 100), paint);
1187
1188 builder.Restore();
1189
1190 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1191 }

## ◆ TEST_P() [24/454]

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

Definition at line 1072 of file aiks_dl_basic_unittests.cc.

1073 {
1074 DisplayListBuilder builder;
1075
1076 DlPaint red;
1077 red.setColor(DlColor::kRed());
1078
1079 DlPaint green;
1080 green.setColor(DlColor::kGreen());
1081
1082 DlPaint blue;
1083 blue.setColor(DlColor::kBlue());
1084
1085 DlPaint save;
1086 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1087
1088 SkRect huge_bounds = SkRect::MakeXYWH(0, 0, 100000, 100000);
1089 builder.SaveLayer(&huge_bounds, &save);
1090
1091 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), red);
1092 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100), green);
1093 builder.DrawRect(SkRect::MakeXYWH(20, 20, 100, 100), blue);
1094
1095 builder.Restore();
1096
1097 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1098 }

## ◆ TEST_P() [25/454]

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

Definition at line 1160 of file aiks_dl_basic_unittests.cc.

1160 {
1161 DisplayListBuilder builder;
1162
1163 DlPaint red;
1164 red.setColor(DlColor::kRed());
1165 builder.Skew(2, 5);
1166 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), red);
1167
1168 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1169 }

## ◆ TEST_P() [26/454]

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

Definition at line 928 of file aiks_dl_unittests.cc.

928 {
929 DisplayListBuilder recorder_canvas;
930 DlPaint paint;
931 paint.setColor(DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0));
932 recorder_canvas.DrawRect(SkRect::MakeXYWH(100.0, 100.0, 600, 600), paint);
933 paint.setColor(DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0));
934 recorder_canvas.DrawRect(SkRect::MakeXYWH(200.0, 200.0, 600, 600), paint);
935
936 DisplayListBuilder canvas;
937 AiksContext renderer(GetContext(), nullptr);
938 paint.setColor(DlColor::kTransparent());
939 canvas.DrawPaint(paint);
940
941 auto image =
942 DisplayListToTexture(recorder_canvas.Build(), {1000, 1000}, renderer);
943 if (image) {
944 canvas.DrawImage(DlImageImpeller::Make(image), {}, {});
945 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
946 canvas.DrawRect(SkRect::MakeSize({1000, 1000}), paint);
947 }
948
949 ASSERT_TRUE(OpenPlaygroundHere(canvas.Build()));
950 }

References impeller::DisplayListToTexture(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [27/454]

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

Definition at line 62 of file aiks_dl_blend_unittests.cc.

62 {
63 DisplayListBuilder builder;
64
65 SkRect layer_rect = SkRect::MakeXYWH(0, 0, 500, 500);
66 builder.ClipRect(layer_rect);
67
68 DlPaint save_paint;
69 save_paint.setColorFilter(DlBlendColorFilter::Make(
70 DlColor::RGBA(0, 1, 0, 0.5), DlBlendMode::kDifference));
71 builder.SaveLayer(&layer_rect, &save_paint);
72
73 DlPaint paint;
74 paint.setColor(DlColor::kBlack());
75 builder.DrawPaint(paint);
76 paint.setColor(DlColor::kWhite());
77 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
78 builder.Restore();
79
80 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
81 }

## ◆ TEST_P() [28/454]

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

Definition at line 242 of file aiks_dl_blur_unittests.cc.

242 {
243 DisplayListBuilder builder;
244
245 DlPaint paint;
246 paint.setColor(DlColor::kCornflowerBlue());
247 builder.DrawCircle({100, 100}, 50, paint);
248
249 paint.setColor(DlColor::kGreenYellow());
250 builder.DrawCircle({300, 200}, 100, paint);
251
252 paint.setColor(DlColor::kDarkMagenta());
253 builder.DrawCircle({140, 170}, 75, paint);
254
255 paint.setColor(DlColor::kOrangeRed());
256 builder.DrawCircle({180, 120}, 100, paint);
257
258 SkRRect rrect =
259 SkRRect::MakeRectXY(SkRect::MakeLTRB(75, 50, 375, 275), 20, 20);
260 builder.ClipRRect(rrect);
261
262 DlPaint save_paint;
263 save_paint.setBlendMode(DlBlendMode::kSrc);
264 auto backdrop_filter = DlBlurImageFilter::Make(30, 30, DlTileMode::kClamp);
265 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
266 builder.Restore();
267
268 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
269 }

## ◆ TEST_P() [29/454]

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

Definition at line 271 of file aiks_dl_blur_unittests.cc.

271 {
272 DisplayListBuilder builder;
273
274 DlPaint paint;
275 paint.setColor(DlColor::kGreen());
276 builder.DrawCircle({400, 400}, 300, paint);
277
278 DlPaint save_paint;
279 save_paint.setBlendMode(DlBlendMode::kSrc);
280
281 auto backdrop_filter =
282 DlBlurImageFilter::Make(999999, 999999, DlTileMode::kClamp);
283 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
284 builder.Restore();
285
286 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
287 }

## ◆ TEST_P() [30/454]

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

Definition at line 205 of file aiks_dl_blur_unittests.cc.

205 {
206 auto callback = [&]() -> sk_sp<DisplayList> {
207 static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
208 static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
209 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
210
211 DisplayListBuilder builder;
212 DlPaint paint;
213 paint.setColor(DlColor::kCornflowerBlue());
214 builder.DrawCircle({100, 100}, 50, paint);
215
216 paint.setColor(DlColor::kGreenYellow());
217 builder.DrawCircle({300, 200}, 100, paint);
218
219 paint.setColor(DlColor::kDarkMagenta());
220 builder.DrawCircle({140, 170}, 75, paint);
221
222 paint.setColor(DlColor::kOrangeRed());
223 builder.DrawCircle({180, 120}, 100, paint);
224
225 SkRRect rrect =
226 SkRRect::MakeRectXY(SkRect::MakeLTRB(a.x, a.y, b.x, b.y), 20, 20);
227 builder.ClipRRect(rrect);
228
229 DlPaint save_paint;
230 save_paint.setBlendMode(DlBlendMode::kSrc);
231
232 auto backdrop_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kClamp);
233 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
234 builder.Restore();
235
236 return builder.Build();
237 };
238
239 ASSERT_TRUE(OpenPlaygroundHere(callback));
240 }

References impeller::saturated::b, impeller::DrawPlaygroundLine(), and impeller::Color::White().

## ◆ TEST_P() [31/454]

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

Definition at line 786 of file aiks_dl_basic_unittests.cc.

786 {
787 DisplayListBuilder builder;
788
789 builder.Scale(GetContentScale().x, GetContentScale().y);
790
791 // Draw something interesting in the background.
792 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
793 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
794 std::vector<Scalar> stops = {
795 0.0,
796 1.0,
797 };
798 DlPaint paint;
799 paint.setColorSource(DlColorSource::MakeLinear(
800 /*start_point=*/{0, 0}, //
801 /*end_point=*/{100, 100}, //
802 /*stop_count=*/2, //
803 /*colors=*/colors.data(), //
804 /*stops=*/stops.data(), //
805 /*tile_mode=*/DlTileMode::kRepeat //
806 ));
807
808 builder.DrawPaint(paint);
809
810 SkRect clip_rect = SkRect::MakeLTRB(50, 50, 400, 300);
811 SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 100, 100);
812
813 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
814 // the same.
815 builder.ClipRRect(clip_rrect, DlCanvas::ClipOp::kIntersect);
816
817 DlPaint save_paint;
818 auto backdrop_filter = std::make_shared<DlColorFilterImageFilter>(
819 DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kExclusion));
820 builder.SaveLayer(&clip_rect, &save_paint, backdrop_filter.get());
821
822 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
823 }

## ◆ TEST_P() [32/454]

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

Definition at line 289 of file aiks_dl_blur_unittests.cc.

289 {
290 DisplayListBuilder builder;
291 builder.ClipRect(SkRect::MakeXYWH(100, 150, 400, 400));
292
293 DlPaint paint;
294 paint.setColor(DlColor::kGreen());
295 paint.setImageFilter(DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal));
296 builder.DrawCircle({400, 400}, 200, paint);
297 builder.Restore();
298
299 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
300 }

## ◆ TEST_P() [33/454]

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

Definition at line 1407 of file aiks_dl_basic_unittests.cc.

1407 {
1408 DisplayListBuilder builder;
1409
1410 DlPaint paint;
1411 paint.setColor(DlColor::kWhite());
1412 builder.DrawPaint(paint);
1413
1414 // Draw a green circle on the screen.
1415 {
1416 // Increase the clip depth for the savelayer to contend with.
1417 SkPath path = SkPath::Circle(100, 100, 50);
1418 builder.ClipPath(path);
1419
1420 SkRect bounds = SkRect::MakeXYWH(50, 50, 100, 100);
1421 DlPaint save_paint;
1422 builder.SaveLayer(&bounds, &save_paint);
1423
1424 // Fill the layer with white.
1425 paint.setColor(DlColor::kWhite());
1426 builder.DrawRect(SkRect::MakeSize(SkSize{400, 400}), paint);
1427 // Fill the layer with green, but do so with a color blend that can't be
1428 // collapsed into the parent pass.
1429 paint.setColor(DlColor::kGreen());
1430 paint.setBlendMode(DlBlendMode::kHardLight);
1431 builder.DrawRect(SkRect::MakeSize(SkSize{400, 400}), paint);
1432 }
1433
1434 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1435 }

## ◆ TEST_P() [34/454]

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

Definition at line 41 of file aiks_dl_runtime_effect_unittests.cc.

41 {
42 struct FragUniforms {
43 Vector2 iResolution;
44 Scalar iTime;
45 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
46 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
47 uniform_data->resize(sizeof(FragUniforms));
48 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
49
50 DlPaint paint;
51 paint.setColorSource(
52 MakeRuntimeEffect(this, "runtime_stage_example.frag.iplr", uniform_data));
53
54 DisplayListBuilder builder;
55 builder.Save();
56 builder.ClipRRect(
57 SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 400, 400), 10.0, 10.0),
58 DlCanvas::ClipOp::kIntersect);
59 builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), paint);
60 builder.Restore();
61
62 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
63 }

## ◆ TEST_P() [35/454]

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

Definition at line 453 of file aiks_dl_path_unittests.cc.

453 {
454 DisplayListBuilder builder;
455 DlPaint paint;
456 paint.setColor(DlColor::kFuchsia());
457
458 builder.ClipPath(SkPath::Rect(SkRect::MakeXYWH(0, 0, 500, 500)));
459 builder.DrawPath(SkPath::Circle(500, 500, 250), paint);
460
461 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
462 }

## ◆ TEST_P() [36/454]

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

Definition at line 36 of file aiks_dl_basic_unittests.cc.

36 {
37 DisplayListBuilder builder;
38 DlPaint paint;
39 paint.setColor(DlColor::kBlue());
40 SkPath path = SkPath();
41 path.addRect(SkRect::MakeXYWH(100.0, 100.0, 100.0, 100.0));
42 builder.DrawPath(path, paint);
43 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
44 }

## ◆ TEST_P() [37/454]

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

Definition at line 70 of file aiks_dl_basic_unittests.cc.

70 {
71 DisplayListBuilder builder;
72 DlPaint paint;
73 paint.setColor(DlColor::kRed());
74 paint.setColorFilter(
75 DlBlendColorFilter::Make(DlColor::kYellow(), DlBlendMode::kSrcOver));
76 paint.setInvertColors(true);
77
78 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
79 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
80 }

## ◆ TEST_P() [38/454]

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

Definition at line 82 of file aiks_dl_basic_unittests.cc.

82 {
83 DisplayListBuilder builder;
84 DlPaint paint;
85 paint.setColor(DlColor::kRed());
86 paint.setColorFilter(
87 DlBlendColorFilter::Make(DlColor::kYellow(), DlBlendMode::kSrcOver));
88 paint.setInvertColors(true);
89
90 builder.DrawPaint(paint);
91 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
92 }

## ◆ TEST_P() [39/454]

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 }

## ◆ TEST_P() [40/454]

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() [41/454]

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

Definition at line 69 of file aiks_dl_path_unittests.cc.

69 {
70 DisplayListBuilder builder;
71 DlPaint paint;
72 paint.setColor(DlColor::kRed());
73 paint.setStrokeWidth(25);
74 paint.setDrawStyle(DlDrawStyle::kStroke);
75
76 builder.DrawPath(SkPath::Circle(500, 500, 250), paint);
77
78 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
79 }

## ◆ TEST_P() [42/454]

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

Definition at line 374 of file aiks_dl_unittests.cc.

374 {
375 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
376
377 DlPaint paint;
378 paint.setColor(DlColor::kRed());
379 builder.DrawPaint(paint);
380 // Draw an empty savelayer with a destructive blend mode, which will replace
381 // the entire red screen with fully transparent black, except for the green
382 // circle drawn within the layer.
383
384 DlPaint save_paint;
385 save_paint.setBlendMode(DlBlendMode::kSrc);
386 builder.SaveLayer(nullptr, &save_paint);
387
388 DlPaint draw_paint;
389 draw_paint.setColor(DlColor::kGreen());
390 builder.DrawCircle({300, 300}, 100, draw_paint);
391 builder.Restore();
392
393 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
394 }

## ◆ TEST_P() [43/454]

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 }

## ◆ TEST_P() [44/454]

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

Definition at line 156 of file aiks_dl_path_unittests.cc.

156 {
157 DisplayListBuilder builder;
158
159 DlPaint paint;
160 paint.setColor(DlColor::kRed());
161
162 SkPoint radii[4] = {{50, 25}, {25, 50}, {50, 25}, {25, 50}};
163 SkPath path;
164 SkRRect rrect;
165 rrect.setRectRadii(SkRect::MakeXYWH(100, 100, 200, 200), radii);
166 path.addRRect(rrect);
167 path.addCircle(200, 200, 50);
168 path.setFillType(SkPathFillType::kEvenOdd);
169
170 builder.DrawImage(
171 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")), {10, 10},
172 {});
173 builder.DrawPath(path, paint);
174
175 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
176 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [45/454]

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

Definition at line 339 of file aiks_dl_basic_unittests.cc.

339 {
340 DisplayListBuilder builder;
341 DlPaint paint;
342
343 DlColor colors[2] = {
344 DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
345 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0),
346 };
347 DlScalar stops[2] = {
348 0.0,
349 1.0,
350 };
351
352 paint.setColorSource(DlColorSource::MakeLinear(
353 /*start_point=*/{0, 0}, //
354 /*end_point=*/{100, 100}, //
355 /*stop_count=*/2, //
356 /*colors=*/colors, //
357 /*stops=*/stops, //
358 /*tile_mode=*/DlTileMode::kRepeat //
359 ));
360
361 builder.Save();
362 builder.Translate(100, 100);
363 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
364 builder.Restore();
365
366 builder.Save();
367 builder.Translate(100, 400);
368 builder.DrawCircle({100, 100}, 100, paint);
369 builder.Restore();
370 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
371 }

## ◆ TEST_P() [46/454]

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

Definition at line 288 of file aiks_dl_text_unittests.cc.

288 {
289 DisplayListBuilder builder;
290
291 DlPaint paint;
292 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
293 builder.DrawPaint(paint);
294
295 ASSERT_TRUE(RenderTextInCanvasSkia(
296 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
297 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
298 }

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [47/454]

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

Definition at line 316 of file aiks_dl_text_unittests.cc.

316 {
317 DisplayListBuilder builder;
318
319 DlPaint paint;
320 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
321 builder.DrawPaint(paint);
322
323 ASSERT_TRUE(RenderTextInCanvasSkia(
324 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
325 {.color = DlColor::kBlack().modulateOpacity(0.5)}));
326 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
327 }

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [48/454]

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

Definition at line 300 of file aiks_dl_text_unittests.cc.

300 {
301 DisplayListBuilder builder;
302
303 builder.Scale(GetContentScale().x, GetContentScale().y);
304 DlPaint paint;
305 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
306 builder.DrawPaint(paint);
307
308 ASSERT_TRUE(RenderTextInCanvasSkia(
309 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
310 TextRenderOptions{
311 .color = DlColor::kBlue(),
312 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
313 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
314 }

References impeller::testing::TextRenderOptions::color, kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [49/454]

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

Definition at line 184 of file aiks_dl_blur_unittests.cc.

184 {
185 // This case triggers the ForegroundAdvancedBlend path. The color filter
186 // should apply to the color only, and respect the alpha mask.
187 DisplayListBuilder builder;
188 builder.ClipRect(SkRect::MakeXYWH(100, 150, 400, 400));
189
190 DlPaint paint;
191 paint.setColor(
192 DlColor::RGBA(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1.0f));
193
194 Sigma sigma = Radius(20);
195 paint.setMaskFilter(
196 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
197 paint.setColorFilter(
198 DlBlendColorFilter::Make(DlColor::kGreen(), DlBlendMode::kColor));
199 builder.DrawCircle({400, 400}, 200, paint);
200 builder.Restore();
201
202 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
203 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [50/454]

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

Definition at line 165 of file aiks_dl_blur_unittests.cc.

165 {
166 // This case triggers the ForegroundPorterDuffBlend path. The color filter
167 // should apply to the color only, and respect the alpha mask.
168 DisplayListBuilder builder;
169 builder.ClipRect(SkRect::MakeXYWH(100, 150, 400, 400));
170
171 DlPaint paint;
172 paint.setColor(DlColor::kWhite());
173
174 Sigma sigma = Radius(20);
175 paint.setMaskFilter(
176 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
177 paint.setColorFilter(
178 DlBlendColorFilter::Make(DlColor::kGreen(), DlBlendMode::kSrc));
179 builder.DrawCircle({400, 400}, 200, paint);
180
181 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
182 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [51/454]

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 }

## ◆ TEST_P() [52/454]

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() [53/454]

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() [54/454]

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

Definition at line 46 of file aiks_dl_basic_unittests.cc.

46 {
47 DisplayListBuilder builder;
48 DlPaint paint;
49 paint.setColor(DlColor::kRed());
50 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
51 builder.DrawImage(image, SkPoint::Make(100.0, 100.0),
52 DlImageSampling::kNearestNeighbor, &paint);
53 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
54 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [55/454]

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

Definition at line 218 of file aiks_dl_basic_unittests.cc.

218 {
219 DisplayListBuilder builder;
220 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
221
222 SkSize image_half_size = SkSize::Make(image->dimensions().fWidth * 0.5f,
223 image->dimensions().fHeight * 0.5f);
224
225 // Render the bottom right quarter of the source image in a stretched rect.
226 auto source_rect = SkRect::MakeSize(image_half_size);
227 source_rect =
228 source_rect.makeOffset(image_half_size.fWidth, image_half_size.fHeight);
229
230 builder.DrawImageRect(image, source_rect,
231 SkRect::MakeXYWH(100, 100, 600, 600),
232 DlImageSampling::kNearestNeighbor);
233 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
234 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [56/454]

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

Definition at line 56 of file aiks_dl_basic_unittests.cc.

56 {
57 DisplayListBuilder builder;
58 DlPaint paint;
59 paint.setColor(DlColor::kRed());
60 paint.setColorFilter(
61 DlBlendColorFilter::Make(DlColor::kYellow(), DlBlendMode::kSrcOver));
62 paint.setInvertColors(true);
63 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
64
65 builder.DrawImage(image, SkPoint::Make(100.0, 100.0),
66 DlImageSampling::kNearestNeighbor, &paint);
67 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
68 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [57/454]

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

Definition at line 268 of file aiks_dl_text_unittests.cc.

268 {
269 DisplayListBuilder builder;
270
271 DlPaint paint;
272 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
273 builder.DrawPaint(paint);
274
275 ASSERT_TRUE(RenderTextInCanvasSkia(
276 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
277 "HomemadeApple.ttf"));
278 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
279 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [58/454]

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() [59/454]

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() [60/454]

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 scale, and impeller::Color::ToARGB().

## ◆ TEST_P() [61/454]

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() [62/454]

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() [63/454]

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() [64/454]

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() [65/454]

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 impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [66/454]

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 }

## ◆ TEST_P() [67/454]

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() [68/454]

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() [69/454]

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() [70/454]

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() [71/454]

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() [72/454]

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

Definition at line 153 of file aiks_dl_blur_unittests.cc.

153 {
154 DisplayListBuilder builder;
155
156 DlPaint paint;
157 paint.setColor(DlColor::kGreen());
158 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 99999));
159 builder.DrawCircle({400, 400}, 300, paint);
160 builder.Restore();
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }

## ◆ TEST_P() [73/454]

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 }

## ◆ TEST_P() [74/454]

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

Definition at line 464 of file aiks_dl_path_unittests.cc.

464 {
465 DisplayListBuilder builder;
466
467 DlPaint paint;
468 paint.setColor(DlColor::kRed());
469
470 SkPoint radii[4] = {{50, 50}, {50, 50}, {50, 50}, {50, 50}};
471
472 const Scalar kTriangleHeight = 100;
473 SkRRect rrect;
474 rrect.setRectRadii(
475 SkRect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
476 kTriangleHeight, kTriangleHeight),
477 radii //
478 );
479
480 builder.Translate(200, 200);
481 // Form a path similar to the Material drop slider value indicator. Both
482 // shapes should render identically side-by-side.
483 {
484 SkPath path;
485 path.moveTo(0, kTriangleHeight);
486 path.lineTo(-kTriangleHeight / 2.0f, 0);
487 path.lineTo(kTriangleHeight / 2.0f, 0);
488 path.close();
489 path.addRRect(rrect);
490
491 builder.DrawPath(path, paint);
492 }
493 builder.Translate(100, 0);
494
495 {
496 SkPath path;
497 path.moveTo(0, kTriangleHeight);
498 path.lineTo(-kTriangleHeight / 2.0f, 0);
499 path.lineTo(0, -10);
500 path.lineTo(kTriangleHeight / 2.0f, 0);
501 path.close();
502 path.addRRect(rrect);
503
504 builder.DrawPath(path, paint);
505 }
506
507 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
508 }

## ◆ TEST_P() [75/454]

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

Definition at line 136 of file aiks_dl_path_unittests.cc.

136 {
137 DisplayListBuilder builder;
138
139 DlPaint paint;
140 paint.setColor(DlColor::kRed());
141 paint.setStrokeWidth(50);
142 paint.setDrawStyle(DlDrawStyle::kStroke);
143 paint.setStrokeCap(DlStrokeCap::kRound);
144
145 // Should draw a diagonal pill shape. If flat on either end, the stroke is
146 // rendering wrong.
147 SkPath path;
148 path.moveTo(250, 250);
149 path.quadTo(100, 100, 250, 250);
150
151 builder.DrawPath(path, paint);
152
153 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
154 }

## ◆ TEST_P() [76/454]

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 impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [77/454]

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 impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [78/454]

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() [79/454]

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

Definition at line 373 of file aiks_dl_basic_unittests.cc.

373 {
374 DisplayListBuilder builder;
375 DlPaint paint;
376 paint.setColor(DlColor::kRed());
377
378 SkRRect rrect;
379 SkVector radii[4] = {
380 SkVector{50, 25},
381 SkVector{25, 50},
382 SkVector{50, 25},
383 SkVector{25, 50},
384 };
385 rrect.setRectRadii(SkRect::MakeXYWH(100, 100, 500, 500), radii);
386
387 builder.DrawRRect(rrect, paint);
388
389 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
390 }

## ◆ TEST_P() [80/454]

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

Definition at line 236 of file aiks_dl_basic_unittests.cc.

236 {
237 DisplayListBuilder builder;
238 builder.Scale(GetContentScale().x, GetContentScale().y);
239 DlPaint paint;
240
241 paint.setColor(DlColor::kWhite());
242 builder.DrawPaint(paint);
243
244 auto draw = [&builder](const DlPaint& paint, Scalar x, Scalar y) {
245 builder.Save();
246 builder.Translate(x, y);
247 {
248 builder.Save();
249 builder.ClipRect(SkRect::MakeLTRB(50, 50, 150, 150));
250 builder.DrawPaint(paint);
251 builder.Restore();
252 }
253 {
254 builder.Save();
255 builder.ClipOval(SkRect::MakeLTRB(200, 50, 300, 150));
256 builder.DrawPaint(paint);
257 builder.Restore();
258 }
259 {
260 builder.Save();
261 builder.ClipRRect(
262 SkRRect::MakeRectXY(SkRect::MakeLTRB(50, 200, 150, 300), 20, 20));
263 builder.DrawPaint(paint);
264 builder.Restore();
265 }
266 {
267 builder.Save();
268 builder.ClipRRect(
269 SkRRect::MakeRectXY(SkRect::MakeLTRB(200, 230, 300, 270), 20, 20));
270 builder.DrawPaint(paint);
271 builder.Restore();
272 }
273 {
274 builder.Save();
275 builder.ClipRRect(
276 SkRRect::MakeRectXY(SkRect::MakeLTRB(230, 200, 270, 300), 20, 20));
277 builder.DrawPaint(paint);
278 builder.Restore();
279 }
280 builder.Restore();
281 };
282
283 paint.setColor(DlColor::kBlue());
284 draw(paint, 0, 0);
285
286 DlColor gradient_colors[7] = {
287 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
288 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
289 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
290 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
291 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
292 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
293 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
294 };
295 Scalar stops[7] = {
296 0.0,
297 (1.0 / 6.0) * 1,
298 (1.0 / 6.0) * 2,
299 (1.0 / 6.0) * 3,
300 (1.0 / 6.0) * 4,
301 (1.0 / 6.0) * 5,
302 1.0,
303 };
304 auto texture = CreateTextureForFixture("airplane.jpg",
305 /*enable_mipmapping=*/true);
306 auto image = DlImageImpeller::Make(texture);
307
308 paint.setColorSource(DlColorSource::MakeRadial(
309 {500, 600}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
310 draw(paint, 0, 300);
311
312 DlImageColorSource image_source(image, DlTileMode::kRepeat,
313 DlTileMode::kRepeat,
314 DlImageSampling::kNearestNeighbor);
315 paint.setColorSource(&image_source);
316 draw(paint, 300, 0);
317
318 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
319 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [81/454]

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

Definition at line 147 of file aiks_dl_text_unittests.cc.

147 {
148 DisplayListBuilder builder;
149
150 DlPaint paint;
151 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
152 builder.DrawPaint(paint);
153
154 ASSERT_TRUE(RenderTextInCanvasSkia(
155 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
156 "Roboto-Regular.ttf",
157 {
158 .stroke = true,
159 }));
160 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
161 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [82/454]

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

Definition at line 105 of file aiks_dl_path_unittests.cc.

105 {
106 DisplayListBuilder builder;
107 DlPaint paint;
108 paint.setColor(DlColor::kRed());
109 paint.setStrokeWidth(200);
110 paint.setDrawStyle(DlDrawStyle::kStroke);
111
112 SkPath path;
113 path.arcTo(SkRect::MakeXYWH(100, 100, 200, 200), 0, 90, false);
114
115 builder.DrawPath(path, paint);
116
117 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
118 }

## ◆ TEST_P() [83/454]

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

Definition at line 120 of file aiks_dl_path_unittests.cc.

120 {
121 DisplayListBuilder builder;
122
123 DlPaint paint;
124 paint.setColor(DlColor::kRed());
125 paint.setStrokeWidth(20);
126 paint.setDrawStyle(DlDrawStyle::kStroke);
127
128 SkPath path;
129 path.moveTo(0, 200);
130 path.cubicTo(50, 400, 350, 0, 400, 200);
131
132 builder.DrawPath(path, paint);
133 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
134 }

## ◆ TEST_P() [84/454]

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

Definition at line 57 of file aiks_dl_path_unittests.cc.

57 {
58 DisplayListBuilder builder;
59 DlPaint paint;
60 paint.setColor(DlColor::kRed());
61 paint.setStrokeWidth(20);
62 paint.setDrawStyle(DlDrawStyle::kStroke);
63
64 builder.DrawPath(SkPath::Line({200, 100}, {800, 100}), paint);
65
66 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
67 }

## ◆ TEST_P() [85/454]

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

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

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

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

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

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() [91/454]

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

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

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() [94/454]

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

Definition at line 118 of file aiks_dl_text_unittests.cc.

118 {
119 DisplayListBuilder builder;
120
121 DlPaint paint;
122 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
123 builder.DrawPaint(paint);
124 ASSERT_TRUE(RenderTextInCanvasSkia(
125 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
126 "Roboto-Regular.ttf"));
127
128 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
129 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [95/454]

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

Definition at line 207 of file aiks_dl_text_unittests.cc.

207 {
208 DisplayListBuilder builder;
209
210 DlPaint paint;
211 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
212 builder.DrawPaint(paint);
213
214 ASSERT_TRUE(RenderTextInCanvasSTB(
215 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
216 "Roboto-Regular.ttf"));
217
218 SetTypographerContext(TypographerContextSTB::Make());
219 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
220 }

References RenderTextInCanvasSTB().

## ◆ TEST_P() [96/454]

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

Definition at line 193 of file aiks_dl_text_unittests.cc.

193 {
194 DisplayListBuilder builder;
195
196 DlPaint paint;
197 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
198 builder.DrawPaint(paint);
199 builder.Scale(2.625, 2.625);
200
201 ASSERT_TRUE(RenderTextInCanvasSkia(
202 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
203 "Roboto-Regular.ttf"));
204 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
205 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [97/454]

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

Definition at line 179 of file aiks_dl_text_unittests.cc.

179 {
180 DisplayListBuilder builder;
181
182 DlPaint paint;
183 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
184 builder.DrawPaint(paint);
185 builder.Scale(0.5, 0.5);
186
187 ASSERT_TRUE(RenderTextInCanvasSkia(
188 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
189 "Roboto-Regular.ttf"));
190 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
191 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [98/454]

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

Definition at line 131 of file aiks_dl_text_unittests.cc.

131 {
132 DisplayListBuilder builder;
133
134 DlPaint paint;
135 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
136 builder.DrawPaint(paint);
137 builder.Translate(1000, 0);
138 builder.Scale(-1, 1);
139
140 ASSERT_TRUE(RenderTextInCanvasSkia(
141 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
142 "Roboto-Regular.ttf"));
143
144 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
145 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [99/454]

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

Definition at line 329 of file aiks_dl_text_unittests.cc.

329 {
330 DisplayListBuilder builder;
331
332 DlPaint paint;
333 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 0.1));
334 builder.DrawPaint(paint);
335
336 builder.Translate(100, 100);
337 builder.Scale(0.5, 0.5);
338
339 // Blend the layer with the parent pass using kClear to expose the coverage.
340 paint.setBlendMode(DlBlendMode::kClear);
341 builder.SaveLayer(nullptr, &paint);
342 ASSERT_TRUE(RenderTextInCanvasSkia(
343 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
344 "Roboto-Regular.ttf"));
345 builder.Restore();
346
347 // Render the text again over the cleared coverage rect.
348 ASSERT_TRUE(RenderTextInCanvasSkia(
349 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
350 "Roboto-Regular.ttf"));
351
352 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
353 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [100/454]

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

Definition at line 355 of file aiks_dl_text_unittests.cc.

355 {
356 DisplayListBuilder builder;
357 builder.Translate(200, 150);
358
359 // Construct the text blob.
360 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
361 ASSERT_NE(mapping, nullptr);
362
363 Scalar font_size = 80;
364 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
365 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
366
367 DlPaint text_paint;
368 text_paint.setColor(DlColor::kBlue().withAlpha(255 * 0.8));
369
370 struct {
371 SkPoint position;
372 const char* text;
373 } text[] = {{SkPoint::Make(0, 0), "0F0F0F0"},
374 {SkPoint::Make(1, 2), "789"},
375 {SkPoint::Make(1, 3), "456"},
376 {SkPoint::Make(1, 4), "123"},
377 {SkPoint::Make(0, 6), "0F0F0F0"}};
378 for (auto& t : text) {
379 builder.Save();
380 builder.Translate(t.position.x() * font_size * 2,
381 t.position.y() * font_size * 1.1);
382 {
383 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
384 ASSERT_NE(blob, nullptr);
385 auto frame = MakeTextFrameFromTextBlobSkia(blob);
386 builder.DrawTextFrame(frame, 0, 0, text_paint);
387 }
388 builder.Restore();
389 }
390
391 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
392 }

References font_size, and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [101/454]

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

Definition at line 163 of file aiks_dl_text_unittests.cc.

163 {
164 DisplayListBuilder builder;
165
166 DlPaint paint;
167 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
168 builder.DrawPaint(paint);
169
170 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "LMNOP VWXYZ",
171 "Roboto-Medium.ttf",
172 {
173 .stroke = true,
174 .stroke_width = 4,
175 }));
176 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
177 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [102/454]

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

Definition at line 453 of file aiks_dl_text_unittests.cc.

453 {
454 // Verifies that text scales are clamped to work around
455 // https://github.com/flutter/flutter/issues/136112 .
456
457 DisplayListBuilder builder;
458
459 DlPaint save_paint;
460 builder.SaveLayer(nullptr, &save_paint);
461 builder.Transform(SkM44::ColMajor(Matrix(2000, 0, 0, 0, //
462 0, 2000, 0, 0, //
463 0, 0, -1, 9000, //
464 0, 0, -1, 7000 //
465 )
466 .m));
467
468 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
469 "Roboto-Regular.ttf"));
470 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
471 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [103/454]

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

Definition at line 473 of file aiks_dl_text_unittests.cc.

473 {
474 DisplayListBuilder text_builder;
475 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), text_builder, "Hello world",
476 "Roboto-Regular.ttf"));
477 auto text_display_list = text_builder.Build();
478
479 DisplayListBuilder builder;
480
481 Matrix matrix = Matrix::MakeRow(2.0, 0.0, 0.0, 0.0, //
482 0.0, 2.0, 0.0, 0.0, //
483 0.0, 0.0, 1.0, 0.0, //
484 0.0, 0.002, 0.0, 1.0);
485
486 DlPaint save_paint;
487 SkRect window_bounds =
488 SkRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
489 builder.SaveLayer(&window_bounds, &save_paint);
490 builder.Transform(SkM44::ColMajor(matrix.m));
491 builder.DrawDisplayList(text_display_list, 1.0f);
492 builder.Restore();
493
494 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
495 }

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

## ◆ TEST_P() [104/454]

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

Definition at line 81 of file aiks_dl_path_unittests.cc.

81 {
82 DisplayListBuilder builder;
83 DlPaint paint;
84 paint.setColor(DlColor::kRed());
85 paint.setStrokeWidth(100);
86 paint.setDrawStyle(DlDrawStyle::kStroke);
87
88 builder.DrawPath(SkPath::Circle(100, 100, 50), paint);
89
90 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
91 }

## ◆ TEST_P() [105/454]

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

Definition at line 93 of file aiks_dl_path_unittests.cc.

93 {
94 DisplayListBuilder builder;
95 DlPaint paint;
96 paint.setColor(DlColor::kRed());
97 paint.setStrokeWidth(0.01);
98 paint.setDrawStyle(DlDrawStyle::kStroke);
99
100 builder.DrawPath(SkPath::Circle(100, 100, 50), paint);
101
102 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
103 }

## ◆ TEST_P() [106/454]

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

Definition at line 197 of file aiks_dl_basic_unittests.cc.

197 {
198 CanRenderTiledTexture(this, DlTileMode::kClamp);
199 }

## ◆ TEST_P() [107/454]

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

Definition at line 213 of file aiks_dl_basic_unittests.cc.

213 {
214 CanRenderTiledTexture(this, DlTileMode::kClamp,
215 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
216 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [108/454]

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

Definition at line 209 of file aiks_dl_basic_unittests.cc.

209 {
210 CanRenderTiledTexture(this, DlTileMode::kDecal);
211 }

## ◆ TEST_P() [109/454]

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

Definition at line 205 of file aiks_dl_basic_unittests.cc.

205 {
206 CanRenderTiledTexture(this, DlTileMode::kMirror);
207 }

## ◆ TEST_P() [110/454]

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

Definition at line 201 of file aiks_dl_basic_unittests.cc.

201 {
202 CanRenderTiledTexture(this, DlTileMode::kRepeat);
203 }

## ◆ TEST_P() [111/454]

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 349 of file aiks_dl_unittests.cc.

349 {
350 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
351
352 DlPaint paint;
353 paint.setColor(DlColor::kRed());
354 builder.DrawPaint(paint);
355
356 // Draw two overlapping subpixel circles.
357 builder.SaveLayer({});
358
359 DlPaint yellow_paint;
360 yellow_paint.setColor(DlColor::kYellow());
361 builder.DrawCircle({100, 100}, 0.1, yellow_paint);
362 builder.Restore();
363 builder.SaveLayer({});
364 builder.DrawCircle({100, 100}, 0.1, yellow_paint);
365 builder.Restore();
366
367 DlPaint draw_paint;
368 draw_paint.setColor(DlColor::kGreen());
369 builder.DrawPaint(draw_paint);
370
371 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
372 }

## ◆ TEST_P() [112/454]

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 }

## ◆ TEST_P() [113/454]

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

Definition at line 321 of file aiks_dl_basic_unittests.cc.

321 {
322 DisplayListBuilder builder;
323
324 DlPaint red;
325 red.setColor(DlColor::kRed());
326
327 DlPaint alpha;
328 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
329
330 builder.SaveLayer(nullptr, &alpha);
331
332 builder.DrawCircle({125, 125}, 125, red);
333
334 builder.Restore();
335
336 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
337 }

## ◆ TEST_P() [114/454]

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

Definition at line 67 of file canvas_unittests.cc.

67 {
68 ContentContext context(GetContext(), nullptr);
69 auto canvas = CreateTestCanvas(context);
70
71 ASSERT_EQ(canvas->GetSaveCount(), 1u);
72 ASSERT_EQ(canvas->Restore(), false);
73
74 canvas->Translate(Size{100, 100});
75 canvas->Save(10);
76 ASSERT_EQ(canvas->GetSaveCount(), 2u);
77 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
78 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
79 ASSERT_TRUE(canvas->Restore());
80 ASSERT_EQ(canvas->GetSaveCount(), 1u);
81 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
82 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
83 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [115/454]

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

Definition at line 85 of file canvas_unittests.cc.

85 {
86 ContentContext context(GetContext(), nullptr);
87 auto canvas = CreateTestCanvas(context);
88
89 Matrix identity;
90 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), identity);
91 canvas->Translate(Size{100, 100});
92 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
93 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
94 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [116/454]

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

Definition at line 486 of file aiks_dl_blend_unittests.cc.

486 {
487 DisplayListBuilder builder;
488
489 DlPaint blue;
490 blue.setColor(DlColor::kBlue());
491 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600.0, 600.0), blue);
492
493 DlPaint clear;
494 clear.setBlendMode(DlBlendMode::kClear);
495
496 builder.DrawCircle({300.0, 300.0}, 200.0, clear);
497
498 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
499 }

## ◆ TEST_P() [117/454]

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

Definition at line 343 of file aiks_dl_blur_unittests.cc.

343 {
344 DisplayListBuilder builder;
345 DlPaint paint;
346 paint.setColor(DlColor::kBlue());
347 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600.0, 600.0), paint);
348
349 DlPaint clear;
350 clear.setBlendMode(DlBlendMode::kClear);
351 clear.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
352
353 builder.DrawCircle({300.0, 300.0}, 200.0, clear);
354
355 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
356 }

## ◆ TEST_P() [118/454]

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

Definition at line 1016 of file aiks_dl_basic_unittests.cc.

1016 {
1017 SetWindowSize({400, 400});
1018 DisplayListBuilder builder;
1019
1020 builder.Scale(GetContentScale().x, GetContentScale().y);
1021
1022 DlPaint paint;
1023 paint.setColor(DlColor::kRed());
1024 builder.DrawRect(SkRect::MakeLTRB(200, 200, 300, 300), paint);
1025
1026 paint.setImageFilter(DlMatrixImageFilter::Make(SkMatrix::Scale(2, 2),
1027 DlImageSampling::kLinear));
1028 builder.SaveLayer(nullptr, &paint);
1029 // Draw a rectangle that would fully cover the parent pass size, but not
1030 // the subpass that it is rendered in.
1031 paint.setColor(DlColor::kGreen());
1032 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
1033 // Draw a bigger rectangle to force the subpass to be bigger.
1034
1035 paint.setColor(DlColor::kRed());
1036 builder.DrawRect(SkRect::MakeLTRB(0, 0, 800, 800), paint);
1037 builder.Restore();
1038
1039 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1040 }

## ◆ TEST_P() [119/454]

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

Definition at line 326 of file aiks_dl_blur_unittests.cc.

326 {
327 DisplayListBuilder builder;
328 builder.Translate(0, -400);
329 DlPaint paint;
330
331 Sigma sigma = Radius{120 * 3};
332 paint.setMaskFilter(
333 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
334 paint.setColor(DlColor::kRed());
335
336 SkPath path = SkPath::Rect(SkRect::MakeLTRB(0, 0, 800, 800));
337 path.addCircle(0, 0, 0.5);
338 builder.DrawPath(path, paint);
339
340 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
341 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [120/454]

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

Definition at line 302 of file aiks_dl_blur_unittests.cc.

302 {
303 auto callback = [&]() -> sk_sp<DisplayList> {
304 static PlaygroundPoint playground_point(Point(400, 400), 20,
305 Color::Green());
306 auto point = DrawPlaygroundPoint(playground_point);
307
308 DisplayListBuilder builder;
309 auto location = point - Point(400, 400);
310 builder.Translate(location.x, location.y);
311
312 DlPaint paint;
313 Sigma sigma = Radius{120 * 3};
314 paint.setMaskFilter(
315 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
316 paint.setColor(DlColor::kRed());
317
318 SkPath path = SkPath::Rect(SkRect::MakeLTRB(0, 0, 800, 800));
319 path.addCircle(0, 0, 0.5);
320 builder.DrawPath(path, paint);
321 return builder.Build();
322 };
323 ASSERT_TRUE(OpenPlaygroundHere(callback));
324 }

References impeller::DrawPlaygroundPoint(), impeller::Color::Green(), and impeller::Sigma::sigma.

## ◆ TEST_P() [121/454]

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 }

## ◆ TEST_P() [122/454]

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

Definition at line 39 of file aiks_dl_unittests.cc.

39 {
40 DisplayListBuilder builder;
41
42 DlPaint paint;
43 paint.setColor(DlColor::kYellow());
44 paint.setBlendMode(DlBlendMode::kSrc);
45 builder.DrawPaint(paint);
46
47 DlPaint save_paint;
48 save_paint.setBlendMode(DlBlendMode::kMultiply);
49 builder.SaveLayer(nullptr, &save_paint);
50
51 DlPaint draw_paint;
52 draw_paint.setColor(DlColor::kCornflowerBlue().modulateOpacity(0.75f));
53 builder.DrawPaint(draw_paint);
54
55 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
56 }

## ◆ TEST_P() [123/454]

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

Definition at line 58 of file aiks_dl_unittests.cc.

58 {
59 // Bug: https://github.com/flutter/flutter/issues/131576
60 DisplayListBuilder builder;
61
62 DlPaint paint;
63 paint.setColor(DlColor::kYellow());
64 paint.setBlendMode(DlBlendMode::kSrc);
65 builder.DrawPaint(paint);
66
67 auto filter = DlBlurImageFilter::Make(20.0, 20.0, DlTileMode::kDecal);
68 builder.SaveLayer(nullptr, nullptr, filter.get());
69
70 DlPaint draw_paint;
71 draw_paint.setColor(DlColor::kCornflowerBlue());
72 builder.DrawPaint(draw_paint);
73
74 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
75 }

## ◆ TEST_P() [124/454]

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

Definition at line 251 of file aiks_dl_blend_unittests.cc.

251 {
252 bool has_color_filter = true;
253 auto callback = [&]() -> sk_sp<DisplayList> {
254 if (AiksTest::ImGuiBegin("Controls", nullptr,
255 ImGuiWindowFlags_AlwaysAutoResize)) {
256 ImGui::Checkbox("has color filter", &has_color_filter);
257 ImGui::End();
258 }
259
260 DisplayListBuilder builder;
261 builder.Scale(GetContentScale().x, GetContentScale().y);
262
263 auto src_image =
264 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
265 auto dst_image =
266 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
267
268 std::vector<DlBlendMode> blend_modes = {
269 DlBlendMode::kScreen, DlBlendMode::kOverlay,
270 DlBlendMode::kDarken, DlBlendMode::kLighten,
271 DlBlendMode::kColorDodge, DlBlendMode::kColorBurn,
272 DlBlendMode::kHardLight, DlBlendMode::kSoftLight,
273 DlBlendMode::kDifference, DlBlendMode::kExclusion,
274 DlBlendMode::kMultiply, DlBlendMode::kHue,
275 DlBlendMode::kSaturation, DlBlendMode::kColor,
276 DlBlendMode::kLuminosity,
277 };
278
279 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
280 builder.Save();
281 builder.Translate((i % 5) * 200, (i / 5) * 200);
282 builder.Scale(0.4, 0.4);
283 {
284 DlPaint dstPaint;
285 builder.DrawImage(dst_image, {0, 0}, DlImageSampling::kMipmapLinear,
286 &dstPaint);
287 }
288 {
289 DlPaint srcPaint;
290 srcPaint.setBlendMode(blend_modes[i]);
291 if (has_color_filter) {
292 std::shared_ptr<const DlColorFilter> color_filter =
293 DlBlendColorFilter::Make(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
294 DlBlendMode::kSrcIn);
295 srcPaint.setColorFilter(color_filter);
296 }
297 builder.DrawImage(src_image, {0, 0}, DlImageSampling::kMipmapLinear,
298 &srcPaint);
299 }
300 builder.Restore();
301 }
302 return builder.Build();
303 };
304 ASSERT_TRUE(OpenPlaygroundHere(callback));
305 }

References impeller::AiksPlayground::ImGuiBegin(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [125/454]

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

Definition at line 310 of file aiks_dl_blend_unittests.cc.

310 {
311 if (GetParam() != PlaygroundBackend::kMetal) {
312 GTEST_SKIP()
313 << "This backend doesn't yet support setting device capabilities.";
314 }
315 if (!WillRenderSomething()) {
316 GTEST_SKIP() << "This test requires playgrounds.";
317 }
318
319 std::shared_ptr<const Capabilities> old_capabilities =
320 GetContext()->GetCapabilities();
321 auto mock_capabilities = std::make_shared<MockCapabilities>();
322 EXPECT_CALL(*mock_capabilities, SupportsFramebufferFetch())
323 .Times(::testing::AtLeast(1))
324 .WillRepeatedly(::testing::Return(false));
325 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
326 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
327 FLT_FORWARD(mock_capabilities, old_capabilities,
328 GetDefaultDepthStencilFormat);
329 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
330 FLT_FORWARD(mock_capabilities, old_capabilities,
331 SupportsImplicitResolvingMSAA);
332 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
333 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
334 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
335 FLT_FORWARD(mock_capabilities, old_capabilities,
336 SupportsTextureToTextureBlits);
337 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
338 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTriangleFan);
339 FLT_FORWARD(mock_capabilities, old_capabilities,
340 SupportsDecalSamplerAddressMode);
341 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
342
343 bool has_color_filter = true;
344 auto callback = [&]() -> sk_sp<DisplayList> {
345 if (AiksTest::ImGuiBegin("Controls", nullptr,
346 ImGuiWindowFlags_AlwaysAutoResize)) {
347 ImGui::Checkbox("has color filter", &has_color_filter);
348 ImGui::End();
349 }
350
351 DisplayListBuilder builder;
352 builder.Scale(GetContentScale().x, GetContentScale().y);
353
354 auto src_image =
355 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
356 auto dst_image =
357 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
358
359 std::vector<DlBlendMode> blend_modes = {
360 DlBlendMode::kScreen, DlBlendMode::kOverlay,
361 DlBlendMode::kDarken, DlBlendMode::kLighten,
362 DlBlendMode::kColorDodge, DlBlendMode::kColorBurn,
363 DlBlendMode::kHardLight, DlBlendMode::kSoftLight,
364 DlBlendMode::kDifference, DlBlendMode::kExclusion,
365 DlBlendMode::kMultiply, DlBlendMode::kHue,
366 DlBlendMode::kSaturation, DlBlendMode::kColor,
367 DlBlendMode::kLuminosity,
368 };
369
370 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
371 builder.Save();
372 builder.Translate((i % 5) * 200, (i / 5) * 200);
373 builder.Scale(0.4, 0.4);
374 {
375 DlPaint dstPaint;
376 builder.DrawImage(dst_image, {0, 0}, DlImageSampling::kMipmapLinear,
377 &dstPaint);
378 }
379 {
380 DlPaint srcPaint;
381 srcPaint.setBlendMode(blend_modes[i]);
382 if (has_color_filter) {
383 std::shared_ptr<const DlColorFilter> color_filter =
384 DlBlendColorFilter::Make(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
385 DlBlendMode::kMultiply);
386 srcPaint.setColorFilter(color_filter);
387 }
388 builder.DrawImage(src_image, {0, 0}, DlImageSampling::kMipmapLinear,
389 &srcPaint);
390 }
391 builder.Restore();
392 }
393 return builder.Build();
394 };
395 ASSERT_TRUE(OpenPlaygroundHere(callback));
396 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::kMetal, and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [126/454]

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

Definition at line 199 of file aiks_dl_blend_unittests.cc.

199 {
200 bool has_color_filter = true;
201 auto callback = [&]() -> sk_sp<DisplayList> {
202 if (AiksTest::ImGuiBegin("Controls", nullptr,
203 ImGuiWindowFlags_AlwaysAutoResize)) {
204 ImGui::Checkbox("has color filter", &has_color_filter);
205 ImGui::End();
206 }
207
208 DisplayListBuilder builder;
209 builder.Scale(GetContentScale().x, GetContentScale().y);
210
211 auto src_image =
212 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
213 auto dst_image =
214 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
215
216 std::vector<DlBlendMode> blend_modes = {
217 DlBlendMode::kSrc, DlBlendMode::kSrcATop, DlBlendMode::kSrcOver,
218 DlBlendMode::kSrcIn, DlBlendMode::kSrcOut, DlBlendMode::kDst,
219 DlBlendMode::kDstATop, DlBlendMode::kDstOver, DlBlendMode::kDstIn,
220 DlBlendMode::kDstOut, DlBlendMode::kClear, DlBlendMode::kXor};
221
222 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
223 builder.Save();
224 builder.Translate((i % 5) * 200, (i / 5) * 200);
225 builder.Scale(0.4, 0.4);
226 {
227 DlPaint dstPaint;
228 builder.DrawImage(dst_image, {0, 0}, DlImageSampling::kMipmapLinear,
229 &dstPaint);
230 }
231 {
232 DlPaint srcPaint;
233 srcPaint.setBlendMode(blend_modes[i]);
234 if (has_color_filter) {
235 std::shared_ptr<const DlColorFilter> color_filter =
236 DlBlendColorFilter::Make(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
237 DlBlendMode::kSrcIn);
238 srcPaint.setColorFilter(color_filter);
239 }
240 builder.DrawImage(src_image, {0, 0}, DlImageSampling::kMipmapLinear,
241 &srcPaint);
242 }
243 builder.Restore();
244 }
245 return builder.Build();
246 };
247 ASSERT_TRUE(OpenPlaygroundHere(callback));
248 }

References impeller::AiksPlayground::ImGuiBegin(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [127/454]

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

Definition at line 77 of file aiks_dl_unittests.cc.

77 {
78 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
79
80 const float matrix[20] = {
81 -1.0, 0, 0, 1.0, 0, //
82 0, -1.0, 0, 1.0, 0, //
83 0, 0, -1.0, 1.0, 0, //
84 1.0, 1.0, 1.0, 1.0, 0 //
85 };
86 auto filter = DlMatrixColorFilter::Make(matrix);
87
88 DlPaint paint;
89 paint.setColorFilter(filter);
90 builder.SaveLayer(nullptr, &paint);
91
92 builder.Translate(500, 300);
93 builder.Rotate(120); // 120 deg
94
95 DlPaint draw_paint;
96 draw_paint.setColor(DlColor::kBlue());
97 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
98
99 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
100 }

## ◆ TEST_P() [128/454]

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 774 of file aiks_dl_blend_unittests.cc.

774 {
775 // Compare with https://fiddle.skia.org/c/@BlendModes
776
777 BlendModeSelection blend_modes = GetBlendModeSelection();
778
779 auto draw_color_wheel = [](DisplayListBuilder& builder) -> void {
780 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
781 /// cyan domain: r >= 0 (because modulo used is non euclidean)
782 auto color_wheel_sampler = [](Radians r) {
783 Scalar x = r.radians / k2Pi + 1;
784
785 // https://www.desmos.com/calculator/6nhjelyoaj
786 auto color_cycle = [](Scalar x) {
787 Scalar cycle = std::fmod(x, 6.0f);
788 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
789 };
790 return Color(color_cycle(6 * x + 1), //
791 color_cycle(6 * x - 1), //
792 color_cycle(6 * x - 3), //
793 1);
794 };
795
796 DlPaint paint;
797 paint.setBlendMode(DlBlendMode::kSrcOver);
798
799 // Draw a fancy color wheel for the backdrop.
800 // https://www.desmos.com/calculator/xw7kafthwd
801 const int max_dist = 900;
802 for (int i = 0; i <= 900; i++) {
803 Radians r(kPhi / k2Pi * i);
804 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
805 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
806
807 auto color = color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
808 paint.setColor(
809 DlColor::RGBA(color.red, color.green, color.blue, color.alpha));
810 SkPoint position = SkPoint::Make(distance * std::sin(r.radians),
811 -distance * std::cos(r.radians));
812
813 builder.DrawCircle(position, 9 + normalized_distance * 3, paint);
814 }
815 };
816
817 auto callback = [&]() -> sk_sp<DisplayList> {
818 // UI state.
819 static bool cache_the_wheel = true;
820 static int current_blend_index = 3;
821 static float dst_alpha = 1;
822 static float src_alpha = 1;
823 static DlColor color0 = DlColor::kRed();
824 static DlColor color1 = DlColor::kGreen();
825 static DlColor color2 = DlColor::kBlue();
826
827 if (AiksTest::ImGuiBegin("Controls", nullptr,
828 ImGuiWindowFlags_AlwaysAutoResize)) {
829 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
830 ImGui::ListBox("Blending mode", &current_blend_index,
831 blend_modes.blend_mode_names.data(),
832 blend_modes.blend_mode_names.size());
833 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
834 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
835 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
836 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
837 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
838 ImGui::End();
839 }
840
841 DisplayListBuilder builder;
842
843 DlPaint paint;
844 paint.setColor(DlColor::kWhite().withAlpha(dst_alpha * 255));
845 paint.setBlendMode(DlBlendMode::kSrc);
846 builder.SaveLayer(nullptr, &paint);
847 {
848 DlPaint paint;
849 paint.setColor(DlColor::kWhite());
850 builder.DrawPaint(paint);
851
852 builder.SaveLayer(nullptr, nullptr);
853 builder.Scale(GetContentScale().x, GetContentScale().y);
854 builder.Translate(500, 400);
855 builder.Scale(3, 3);
856 draw_color_wheel(builder);
857 builder.Restore();
858 }
859 builder.Restore();
860
861 builder.Scale(GetContentScale().x, GetContentScale().y);
862 builder.Translate(500, 400);
863 builder.Scale(3, 3);
864
865 // Draw 3 circles to a subpass and blend it in.
866 DlPaint save_paint;
867 save_paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
868 save_paint.setBlendMode(static_cast<DlBlendMode>(
869 blend_modes.blend_mode_values[current_blend_index]));
870 builder.SaveLayer(nullptr, &save_paint);
871 {
872 DlPaint paint;
873 paint.setBlendMode(DlBlendMode::kPlus);
874 const Scalar x = std::sin(k2Pi / 3);
875 const Scalar y = -std::cos(k2Pi / 3);
876 paint.setColor(color0);
877 builder.DrawCircle(SkPoint::Make(-x * 45, y * 45), 65, paint);
878 paint.setColor(color1);
879 builder.DrawCircle(SkPoint::Make(0, -45), 65, paint);
880 paint.setColor(color2);
881 builder.DrawCircle(SkPoint::Make(x * 45, y * 45), 65, paint);
882 }
883 builder.Restore();
884
885 return builder.Build();
886 };
887
888 ASSERT_TRUE(OpenPlaygroundHere(callback));
889 }

References impeller::testing::BlendModeSelection::blend_mode_names, impeller::testing::BlendModeSelection::blend_mode_values, color, impeller::saturated::distance, GetBlendModeSelection(), impeller::AiksPlayground::ImGuiBegin(), impeller::k2Pi, impeller::kPhi, and impeller::Radians::radians.

## ◆ TEST_P() [129/454]

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

Definition at line 1114 of file aiks_dl_basic_unittests.cc.

1114 {
1115 DisplayListBuilder builder;
1116
1117 // Render a texture directly.
1118 {
1119 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1120
1121 builder.Save();
1122 builder.Translate(100, 200);
1123 builder.Scale(0.5, 0.5);
1124 builder.DrawImage(image, SkPoint::Make(100.0, 100.0),
1125 DlImageSampling::kNearestNeighbor);
1126 builder.Restore();
1127 }
1128
1129 // Render an offscreen rendered texture.
1130 {
1131 DlPaint alpha;
1132 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1133
1134 builder.SaveLayer(nullptr, &alpha);
1135
1136 DlPaint paint;
1137 paint.setColor(DlColor::kRed());
1138 builder.DrawRect(SkRect::MakeXYWH(000, 000, 100, 100), paint);
1139 paint.setColor(DlColor::kGreen());
1140 builder.DrawRect(SkRect::MakeXYWH(020, 020, 100, 100), paint);
1141 paint.setColor(DlColor::kBlue());
1142 builder.DrawRect(SkRect::MakeXYWH(040, 040, 100, 100), paint);
1143
1144 builder.Restore();
1145 }
1146
1147 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1148 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [130/454]

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

Definition at line 1297 of file aiks_dl_basic_unittests.cc.

1297 {
1298 auto callback = [&]() -> sk_sp<DisplayList> {
1299 DisplayListBuilder builder;
1300 builder.Scale(GetContentScale().x, GetContentScale().y);
1301
1302 DlPaint alpha;
1303 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1304
1305 auto current = Point{25, 25};
1306 const auto offset = Point{25, 25};
1307 const auto size = Size(100, 100);
1308
1309 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1310 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1311 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1312 SkRect bounds = SkRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1313
1314 DlPaint stroke_paint;
1315 stroke_paint.setColor(DlColor::kYellow());
1316 stroke_paint.setStrokeWidth(5);
1317 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1318 builder.DrawRect(bounds, stroke_paint);
1319
1320 builder.SaveLayer(&bounds, &alpha);
1321
1322 DlPaint paint;
1323 paint.setColor(DlColor::kRed());
1324 builder.DrawRect(
1325 SkRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1326
1327 paint.setColor(DlColor::kGreen());
1328 current += offset;
1329 builder.DrawRect(
1330 SkRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1331
1332 paint.setColor(DlColor::kBlue());
1333 current += offset;
1334 builder.DrawRect(
1335 SkRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1336
1337 builder.Restore();
1338
1339 return builder.Build();
1340 };
1341
1342 ASSERT_TRUE(OpenPlaygroundHere(callback));
1343 }

References impeller::DrawPlaygroundLine(), offset, and impeller::Color::White().

## ◆ TEST_P() [131/454]

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

Definition at line 864 of file aiks_dl_unittests.cc.

864 {
865 flutter::DisplayListBuilder sub_builder(true);
866 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
867 flutter::DlPaint(flutter::DlColor::kRed()));
868 auto display_list = sub_builder.Build();
869
870 AiksContext context(GetContext(), nullptr);
871 RenderTarget render_target =
872 context.GetContentContext().GetRenderTargetCache()->CreateOffscreen(
873 *context.GetContext(), {2400, 1800}, 1);
874
875 DisplayListBuilder builder;
876
877 builder.Scale(2.0, 2.0);
878 builder.Translate(-93.0, 0.0);
879
880 // clang-format off
881 builder.TransformFullPerspective(
882 0.8, -0.2, -0.1, -0.0,
883 0.0, 1.0, 0.0, 0.0,
884 1.4, 1.3, 1.0, 0.0,
885 63.2, 65.3, 48.6, 1.1
886 );
887 // clang-format on
888 builder.Translate(35.0, 75.0);
889 builder.DrawDisplayList(display_list, 1.0f);
890
891 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
892 }

References impeller::AiksContext::GetContentContext(), impeller::AiksContext::GetContext(), and impeller::ContentContext::GetRenderTargetCache().

## ◆ TEST_P() [132/454]

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

Definition at line 219 of file aiks_dl_atlas_unittests.cc.

219 {
220 auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
221
222 std::vector<DlColor> colors;
223 colors.reserve(texture_coordinates.size());
224 for (auto i = 0u; i < texture_coordinates.size(); i++) {
225 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
226 }
227 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
228 texture_coordinates.data(), colors.data(),
229 transforms.size(), BlendMode::kSourceOver, {},
230 std::nullopt);
231
232 EXPECT_TRUE(geom.ShouldUseBlend());
233 EXPECT_FALSE(geom.ShouldSkip());
234
235 ContentContext context(GetContext(), nullptr);
236 auto vertex_buffer =
237 geom.CreateBlendVertexBuffer(context.GetTransientsBuffer());
238
239 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
240 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
241 }

References impeller::DlAtlasGeometry::CreateBlendVertexBuffer(), impeller::ContentContext::GetTransientsBuffer(), impeller::kNone, impeller::kSourceOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [133/454]

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

Definition at line 243 of file aiks_dl_atlas_unittests.cc.

243 {
244 auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
245
246 std::vector<DlColor> colors;
247 colors.reserve(texture_coordinates.size());
248 for (auto i = 0u; i < texture_coordinates.size(); i++) {
249 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
250 }
251 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
252 texture_coordinates.data(), colors.data(),
253 transforms.size(), BlendMode::kSource, {}, std::nullopt);
254
255 // Src blend mode means that colors would be ignored, even if provided.
256 EXPECT_FALSE(geom.ShouldUseBlend());
257 EXPECT_FALSE(geom.ShouldSkip());
258 }

References impeller::kSource, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [134/454]

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

Definition at line 201 of file aiks_dl_atlas_unittests.cc.

201 {
202 auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
203
204 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
205 texture_coordinates.data(), nullptr, transforms.size(),
206 BlendMode::kSourceOver, {}, std::nullopt);
207
208 EXPECT_FALSE(geom.ShouldUseBlend());
209 EXPECT_FALSE(geom.ShouldSkip());
210
211 ContentContext context(GetContext(), nullptr);
212 auto vertex_buffer =
213 geom.CreateSimpleVertexBuffer(context.GetTransientsBuffer());
214
215 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
216 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
217 }

References impeller::DlAtlasGeometry::CreateSimpleVertexBuffer(), impeller::ContentContext::GetTransientsBuffer(), impeller::kNone, impeller::kSourceOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [135/454]

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

Definition at line 260 of file aiks_dl_atlas_unittests.cc.

260 {
261 auto [texture_coordinates, transforms, atlas] = CreateDlTestData(this);
262
263 std::vector<DlColor> colors;
264 colors.reserve(texture_coordinates.size());
265 for (auto i = 0u; i < texture_coordinates.size(); i++) {
266 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
267 }
268 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
269 texture_coordinates.data(), colors.data(),
270 transforms.size(), BlendMode::kClear, {}, std::nullopt);
271 EXPECT_TRUE(geom.ShouldSkip());
272 }

References impeller::kClear, and impeller::DlAtlasGeometry::ShouldSkip().

## ◆ TEST_P() [136/454]

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

Definition at line 143 of file aiks_dl_blend_unittests.cc.

143 {
144 DisplayListBuilder builder;
145
146 DlPaint draw_paint;
147 draw_paint.setColor(DlColor::kBlue());
148 builder.DrawPaint(draw_paint);
149 builder.Scale(2, 2);
150 builder.ClipRect(SkRect::MakeLTRB(0, 0, 200, 200));
151
152 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
153 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
154 std::vector<Scalar> stops = {0.0, 1.0};
155
156 DlPaint paint;
157 SkMatrix matrix = SkMatrix::Scale(0.3, 0.3);
158 paint.setColorSource(DlColorSource::MakeLinear(
159 /*start_point=*/{0, 0}, //
160 /*end_point=*/{100, 100}, //
161 /*stop_count=*/colors.size(), //
162 /*colors=*/colors.data(), //
163 /*stops=*/stops.data(), //
164 /*tile_mode=*/DlTileMode::kRepeat, //
165 /*matrix=*/&matrix //
166 ));
167 paint.setBlendMode(DlBlendMode::kLighten);
168
169 builder.DrawCircle({100, 100}, 100, paint);
170 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
171 }

## ◆ TEST_P() [137/454]

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

Definition at line 155 of file aiks_dl_atlas_unittests.cc.

155 {
156 DisplayListBuilder builder;
157 // Draws the image as four squares stiched together.
158 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
159
160 builder.Scale(0.25, 0.25);
161 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
162 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kModulate,
163 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
164
165 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
166 }

## ◆ TEST_P() [138/454]

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

Definition at line 78 of file aiks_dl_atlas_unittests.cc.

78 {
79 DisplayListBuilder builder;
80 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
81
82 builder.Scale(GetContentScale().x, GetContentScale().y);
83 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
84 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kSrcOver,
85 DlImageSampling::kNearestNeighbor, nullptr);
86
87 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
88 }

## ◆ TEST_P() [139/454]

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

Definition at line 138 of file aiks_dl_atlas_unittests.cc.

138 {
139 auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
140 auto size = atlas->impeller_texture()->GetSize();
141 std::vector<SkRect> texture_coordinates = {
142 SkRect::MakeLTRB(0, 0, size.width, size.height)};
143 std::vector<SkRSXform> transforms = {MakeTranslation(0, 0)};
144
145 DisplayListBuilder builder;
146 builder.Scale(GetContentScale().x, GetContentScale().y);
147 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
148 /*colors=*/nullptr, /*count=*/1, DlBlendMode::kSrcOver,
149 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
150
151 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
152 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [140/454]

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

Definition at line 184 of file aiks_dl_atlas_unittests.cc.

184 {
185 DisplayListBuilder builder;
186 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
187 PixelFormat::kB10G10R10A10XR);
188
189 // Draws the image as four squares stiched together.
190 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
191 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
192 DlColor::kBlue(), DlColor::kYellow()};
193
194 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
195 colors.data(), /*count=*/4, DlBlendMode::kPlus,
196 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
197
198 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
199 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [141/454]

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

Definition at line 90 of file aiks_dl_atlas_unittests.cc.

90 {
91 DisplayListBuilder builder;
92 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
93
94 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
95 DlColor::kBlue(), DlColor::kYellow()};
96
97 builder.Scale(GetContentScale().x, GetContentScale().y);
98 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
99 colors.data(), /*count=*/4, DlBlendMode::kModulate,
100 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
101
102 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
103 }

## ◆ TEST_P() [142/454]

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

Definition at line 169 of file aiks_dl_atlas_unittests.cc.

169 {
170 DisplayListBuilder builder;
171 // Draws the image as four squares stiched together.
172 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
173 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
174 DlColor::kBlue(), DlColor::kYellow()};
175
176 builder.Scale(0.25, 0.25);
177 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
178 colors.data(), /*count=*/4, DlBlendMode::kModulate,
179 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
180
181 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
182 }

## ◆ TEST_P() [143/454]

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

Definition at line 105 of file aiks_dl_atlas_unittests.cc.

105 {
106 DisplayListBuilder builder;
107 // Draws the image as four squares stiched together.
108 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
109
110 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
111 DlColor::kBlue(), DlColor::kYellow()};
112
113 builder.Scale(GetContentScale().x, GetContentScale().y);
114 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
115 colors.data(), /*count=*/4, DlBlendMode::kSrcATop,
116 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
117
118 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
119 }

## ◆ TEST_P() [144/454]

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

Definition at line 121 of file aiks_dl_atlas_unittests.cc.

121 {
122 DisplayListBuilder builder;
123 // Draws the image as four squares stiched together slightly
124 // opaque
125 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
126
127 DlPaint paint;
128 paint.setAlpha(128);
129 builder.Scale(GetContentScale().x, GetContentScale().y);
130 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
131 /*colors=*/nullptr, 4, DlBlendMode::kSrcOver,
132 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr,
133 &paint);
134
135 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
136 }

## ◆ TEST_P() [145/454]

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

Definition at line 307 of file aiks_dl_path_unittests.cc.

307 {
308 DisplayListBuilder builder;
309 builder.Scale(GetContentScale().x, GetContentScale().y);
310
311 DlPaint paint;
312 paint.setColor(DlColor::kBlue());
313 paint.setStrokeWidth(10);
314
315 auto draw = [&builder](DlPaint& paint) {
316 for (auto cap :
317 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
318 paint.setStrokeCap(cap);
319 SkPoint origin = {100, 100};
320 builder.DrawLine({150, 100}, {250, 100}, paint);
321 for (int d = 15; d < 90; d += 15) {
322 Matrix m = Matrix::MakeRotationZ(Degrees(d));
323 Point origin = {100, 100};
324 Point p0 = {50, 0};
325 Point p1 = {150, 0};
326 auto a = origin + m * p0;
327 auto b = origin + m * p1;
328
329 builder.DrawLine(SkPoint::Make(a.x, a.y), SkPoint::Make(b.x, b.y),
330 paint);
331 }
332 builder.DrawLine({100, 150}, {100, 250}, paint);
333 builder.DrawCircle({origin}, 35, paint);
334
335 builder.DrawLine({250, 250}, {250, 250}, paint);
336
337 builder.Translate(250, 0);
338 }
339 builder.Translate(-750, 250);
340 };
341
342 std::vector<DlColor> colors = {
343 DlColor::ARGB(1, 0x1f / 255.0, 0.0, 0x5c / 255.0),
344 DlColor::ARGB(1, 0x5b / 255.0, 0.0, 0x60 / 255.0),
345 DlColor::ARGB(1, 0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0),
346 DlColor::ARGB(1, 0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0),
347 DlColor::ARGB(1, 0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0),
348 DlColor::ARGB(1, 0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0),
349 DlColor::ARGB(1, 0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0)};
350 std::vector<Scalar> stops = {
351 0.0,
352 (1.0 / 6.0) * 1,
353 (1.0 / 6.0) * 2,
354 (1.0 / 6.0) * 3,
355 (1.0 / 6.0) * 4,
356 (1.0 / 6.0) * 5,
357 1.0,
358 };
359
360 auto texture = DlImageImpeller::Make(
361 CreateTextureForFixture("airplane.jpg",
362 /*enable_mipmapping=*/true));
363
364 draw(paint);
365
366 paint.setColorSource(DlColorSource::MakeRadial({100, 100}, 200, stops.size(),
367 colors.data(), stops.data(),
368 DlTileMode::kMirror));
369 draw(paint);
370
371 SkMatrix matrix = SkMatrix::Translate(-150, 75);
372 paint.setColorSource(std::make_shared<DlImageColorSource>(
373 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
374 DlImageSampling::kMipmapLinear, &matrix));
375 draw(paint);
376
377 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
378 }

References impeller::saturated::b, impeller::DlImageImpeller::Make(), and impeller::Matrix::MakeRotationZ().

## ◆ TEST_P() [146/454]

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() [147/454]

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

Definition at line 65 of file aiks_dl_runtime_effect_unittests.cc.

65 {
66 struct FragUniforms {
67 Size size;
68 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
69 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
70 uniform_data->resize(sizeof(FragUniforms));
71 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
72
73 DlPaint paint;
74 paint.setColorSource(
75 MakeRuntimeEffect(this, "gradient.frag.iplr", uniform_data));
76
77 DisplayListBuilder builder;
78 builder.Save();
79 builder.Scale(GetContentScale().x, GetContentScale().y);
80 builder.DrawPaint(paint);
81 builder.Restore();
82
83 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
84 }

References impeller::TSize< Scalar >::MakeWH().

## ◆ TEST_P() [148/454]

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

Definition at line 126 of file aiks_dl_blend_unittests.cc.

126 {
127 DlPaint paint;
128 paint.setColor(DlColor::kBlack());
129 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 60));
130
131 DisplayListBuilder builder;
132 paint.setColor(DlColor::kWhite());
133 builder.DrawPaint(paint);
134 paint.setColor(DlColor::kBlack());
135 builder.DrawCircle({300, 300}, 200, paint);
136 paint.setColor(DlColor::kGreen());
137 paint.setBlendMode(DlBlendMode::kScreen);
138 builder.DrawPaint(paint);
139
140 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
141 }

## ◆ TEST_P() [149/454]

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

Definition at line 380 of file aiks_dl_path_unittests.cc.

380 {
381 DisplayListBuilder builder;
382 DlPaint paint;
383 paint.setColor(DlColor::kRed());
384 paint.setDrawStyle(DlDrawStyle::kStroke);
385 paint.setStrokeWidth(10);
386
387 builder.Translate(100, 100);
388 builder.DrawPath(SkPath::Rect(SkRect::MakeSize(SkSize{100, 100})), {paint});
389
390 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
391 }

## ◆ TEST_P() [150/454]

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

Definition at line 393 of file aiks_dl_path_unittests.cc.

393 {
394 DisplayListBuilder builder;
395 DlPaint paint;
396 paint.setColor(DlColor::kRed());
397 paint.setDrawStyle(DlDrawStyle::kStroke);
398 paint.setStrokeWidth(10);
399 paint.setStrokeJoin(DlStrokeJoin::kBevel);
400
401 builder.Translate(100, 100);
402 builder.DrawPath(SkPath::Rect(SkRect::MakeSize(SkSize{100, 100})), paint);
403
404 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
405 }

## ◆ TEST_P() [151/454]

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

Definition at line 414 of file aiks_dl_text_unittests.cc.

414 {
415 DisplayListBuilder builder;
416
417 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
418 0.0, 1.0, 0.0, 0.0, //
419 0.0, 0.0, 1.0, 0.01, //
420 0.0, 0.0, 0.0, 1.0) * //
421 Matrix::MakeRotationY({Degrees{10}});
422
423 builder.Transform(SkM44::ColMajor(matrix.m));
424
425 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
426 "Roboto-Regular.ttf"));
427 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
428 }

References impeller::Matrix::m, RenderTextInCanvasSkia(), and impeller::Matrix::Transform().

## ◆ TEST_P() [152/454]

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

Definition at line 430 of file aiks_dl_text_unittests.cc.

430 {
431 DisplayListBuilder builder;
432
433 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
434 0.0, 1.0, 0.0, 0.0, //
435 0.0, 0.0, 1.0, 0.01, //
436 0.0, 0.0, 0.0, 1.0) * //
437 Matrix::MakeRotationY({Degrees{10}});
438
439 DlPaint save_paint;
440 SkRect window_bounds =
441 SkRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
442 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
443 builder.SaveLayer(&window_bounds, &save_paint);
444 builder.Transform(SkM44::ColMajor(matrix.m));
445
446 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
447 "Roboto-Regular.ttf"));
448
449 builder.Restore();
450 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
451 }

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

## ◆ TEST_P() [153/454]

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

Definition at line 260 of file aiks_dl_vertices_unittests.cc.

260 {
261 auto texture = CreateTextureForFixture("embarcadero.jpg");
262 auto dl_image = DlImageImpeller::Make(texture);
263 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
264 SkPoint::Make(200, 100),
265 SkPoint::Make(300, 300)};
266 std::vector<SkPoint> texture_coordinates = {
267 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
268
269 auto vertices = flutter::DlVertices::Make(
270 flutter::DlVertexMode::kTriangles, 3, positions.data(),
271 texture_coordinates.data(), /*colors=*/nullptr);
272
273 flutter::DisplayListBuilder builder;
274 flutter::DlPaint paint;
275
276 auto image_source = flutter::DlImageColorSource(
277 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
278
279 paint.setColorSource(&image_source);
280 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
281
282 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
283 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [154/454]

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

Definition at line 285 of file aiks_dl_vertices_unittests.cc.

286 {
287 auto texture = CreateTextureForFixture("embarcadero.jpg");
288 auto dl_image = DlImageImpeller::Make(texture);
289 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
290 SkPoint::Make(200, 100),
291 SkPoint::Make(300, 300)};
292 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
293 flutter::DlColor::kGreen(),
294 flutter::DlColor::kWhite()};
295 std::vector<SkPoint> texture_coordinates = {
296 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
297
298 auto vertices = flutter::DlVertices::Make(
299 flutter::DlVertexMode::kTriangles, 3, positions.data(),
300 texture_coordinates.data(), colors.data());
301
302 flutter::DisplayListBuilder builder;
303 flutter::DlPaint paint;
304
305 auto image_source = flutter::DlImageColorSource(
306 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
307
308 paint.setColorSource(&image_source);
309 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
310
311 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
312 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [155/454]

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

Definition at line 205 of file aiks_dl_vertices_unittests.cc.

205 {
206 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
207 SkPoint::Make(200, 100),
208 SkPoint::Make(300, 300)};
209
210 auto vertices = flutter::DlVertices::Make(
211 flutter::DlVertexMode::kTriangles, 3, positions.data(),
212 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
213
214 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
215 flutter::DlColor::kRed()};
216 const float stops[2] = {0.0, 1.0};
217
218 auto linear = flutter::DlColorSource::MakeLinear(
219 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
220 flutter::DlTileMode::kRepeat);
221
222 flutter::DisplayListBuilder builder;
223 flutter::DlPaint paint;
224
225 paint.setColorSource(linear);
226 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
227
228 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
229 }

## ◆ TEST_P() [156/454]

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

Definition at line 231 of file aiks_dl_vertices_unittests.cc.

231 {
232 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
233 SkPoint::Make(200, 100),
234 SkPoint::Make(300, 300)};
235 std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
236 SkPoint::Make(100, 200),
237 SkPoint::Make(300, 300)};
238
239 auto vertices = flutter::DlVertices::Make(
240 flutter::DlVertexMode::kTriangles, 3, positions.data(),
241 texture_coordinates.data(), /*colors=*/nullptr);
242
243 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
244 flutter::DlColor::kRed()};
245 const float stops[2] = {0.0, 1.0};
246
247 auto linear = flutter::DlColorSource::MakeLinear(
248 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
249 flutter::DlTileMode::kRepeat);
250
251 flutter::DisplayListBuilder builder;
252 flutter::DlPaint paint;
253
254 paint.setColorSource(linear);
255 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
256
257 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
258 }

## ◆ TEST_P() [157/454]

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

Definition at line 334 of file aiks_dl_vertices_unittests.cc.

334 {
335 std::vector<SkPoint> positions = {
336 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
337 SkPoint::Make(200, 500)};
338 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
339 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
340 std::vector<flutter::DlColor> colors = {color, color, color, color};
341
342 auto vertices = flutter::DlVertices::Make(
343 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
344 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
345 indices.data());
346
347 flutter::DisplayListBuilder builder;
348 flutter::DlPaint paint;
349 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
350 paint.setColor(flutter::DlColor::kRed());
351
352 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
353 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
354
355 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
356 }

References color.

## ◆ TEST_P() [158/454]

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

Definition at line 314 of file aiks_dl_vertices_unittests.cc.

314 {
315 std::vector<SkPoint> positions = {
316 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
317 SkPoint::Make(200, 500)};
318 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
319
320 auto vertices = flutter::DlVertices::Make(
321 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
322 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
323 indices.data());
324
325 flutter::DisplayListBuilder builder;
326 flutter::DlPaint paint;
327
328 paint.setColor(flutter::DlColor::kRed());
329 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
330
331 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
332 }

## ◆ TEST_P() [159/454]

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

Definition at line 181 of file aiks_dl_vertices_unittests.cc.

181 {
182 // Use negative coordinates and then scale the transform by -1, -1 to make
183 // sure coverage is taking the transform into account.
184 std::vector<SkPoint> positions = {SkPoint::Make(-100, -300),
185 SkPoint::Make(-200, -100),
186 SkPoint::Make(-300, -300)};
187 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
188 flutter::DlColor::kGreen(),
189 flutter::DlColor::kWhite()};
190
191 auto vertices = flutter::DlVertices::Make(
192 flutter::DlVertexMode::kTriangles, 3, positions.data(),
193 /*texture_coordinates=*/nullptr, colors.data());
194
195 flutter::DisplayListBuilder builder;
196 flutter::DlPaint paint;
197
198 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
199 builder.Scale(-1, -1);
200 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
201
202 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
203 }

## ◆ TEST_P() [160/454]

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

Definition at line 387 of file aiks_dl_vertices_unittests.cc.

387 {
388 std::vector<SkPoint> positions_lt = {
389 SkPoint::Make(0, 0), //
390 SkPoint::Make(50, 0), //
391 SkPoint::Make(0, 50), //
392 SkPoint::Make(50, 50), //
393 };
394
395 auto vertices_lt = flutter::DlVertices::Make(
396 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
397 positions_lt.data(),
398 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
399 /*index_count=*/0,
400 /*indices=*/nullptr);
401
402 std::vector<SkPoint> positions_rt = {
403 SkPoint::Make(50, 0), //
404 SkPoint::Make(100, 0), //
405 SkPoint::Make(50, 50), //
406 SkPoint::Make(100, 50), //
407 };
408
409 auto vertices_rt = flutter::DlVertices::Make(
410 flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
411 positions_rt.data(),
412 /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
413 /*index_count=*/0,
414 /*indices=*/nullptr);
415
416 std::vector<SkPoint> positions_lb = {
417 SkPoint::Make(0, 50), //
418 SkPoint::Make(50, 50), //
419 SkPoint::Make(0, 100), //
420 SkPoint::Make(50, 100), //
421 };
422
423 auto vertices_lb = flutter::DlVertices::Make(
424 flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
425 positions_lb.data(),
426 /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
427 /*index_count=*/0,
428 /*indices=*/nullptr);
429
430 std::vector<SkPoint> positions_rb = {
431 SkPoint::Make(50, 50), //
432 SkPoint::Make(100, 50), //
433 SkPoint::Make(50, 100), //
434 SkPoint::Make(100, 100), //
435 };
436
437 auto vertices_rb = flutter::DlVertices::Make(
438 flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
439 positions_rb.data(),
440 /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
441 /*index_count=*/0,
442 /*indices=*/nullptr);
443
444 flutter::DisplayListBuilder builder;
445 flutter::DlPaint paint;
446 flutter::DlPaint rect_paint;
447 rect_paint.setColor(DlColor::kBlue());
448
449 auto runtime_stages =
450 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
451
452 auto runtime_stage =
453 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
454 ASSERT_TRUE(runtime_stage);
455
456 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
457 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
458 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
459 runtime_effect, {}, uniform_data);
460
461 paint.setColorSource(color_source);
462
463 builder.Scale(GetContentScale().x, GetContentScale().y);
464 builder.Save();
465 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), rect_paint);
466 builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
467 builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
468 builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
469 builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
470 builder.Restore();
471
472 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
473 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [161/454]

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

Definition at line 477 of file aiks_dl_vertices_unittests.cc.

478 {
479 std::vector<SkPoint> positions_lt = {
480 SkPoint::Make(200, 200), //
481 SkPoint::Make(250, 200), //
482 SkPoint::Make(200, 250), //
483 SkPoint::Make(250, 250), //
484 };
485
486 auto vertices = flutter::DlVertices::Make(
487 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
488 positions_lt.data(),
489 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
490 /*index_count=*/0,
491 /*indices=*/nullptr);
492
493 flutter::DisplayListBuilder builder;
494 flutter::DlPaint paint;
495 flutter::DlPaint rect_paint;
496 rect_paint.setColor(DlColor::kBlue());
497
498 auto runtime_stages =
499 OpenAssetAsRuntimeStage("runtime_stage_position.frag.iplr");
500
501 auto runtime_stage =
502 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
503 ASSERT_TRUE(runtime_stage);
504
505 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
506 auto rect_data = std::vector<Rect>{Rect::MakeLTRB(200, 200, 250, 250)};
507
508 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
509 uniform_data->resize(rect_data.size() * sizeof(Rect));
510 memcpy(uniform_data->data(), rect_data.data(), uniform_data->size());
511
512 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
513 runtime_effect, {}, uniform_data);
514
515 paint.setColorSource(color_source);
516
517 builder.Scale(GetContentScale().x, GetContentScale().y);
518 builder.DrawRect(SkRect::MakeLTRB(200, 200, 250, 250), rect_paint);
519 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
520
521 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
522 }

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

## ◆ TEST_P() [162/454]

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

Definition at line 358 of file aiks_dl_vertices_unittests.cc.

358 {
359 std::vector<SkPoint> positions = {
360 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
361 SkPoint::Make(200, 500)};
362 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3, 99, 100, 101};
363
364 auto vertices = flutter::DlVertices::Make(
365 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
366 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
367 indices.data());
368
369 EXPECT_EQ(vertices->bounds(), SkRect::MakeLTRB(100, 100, 300, 500));
370
371 flutter::DisplayListBuilder builder;
372 flutter::DlPaint paint;
373 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
374 paint.setColor(flutter::DlColor::kRed());
375
376 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
377 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrc, paint);
378
379 AiksContext renderer(GetContext(), nullptr);
380 std::shared_ptr<Texture> image =
381 DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
382 EXPECT_TRUE(image);
383 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [163/454]

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

Definition at line 1042 of file aiks_dl_basic_unittests.cc.

1042 {
1043 DisplayListBuilder builder;
1044 builder.Scale(GetContentScale().x, GetContentScale().y);
1045
1046 DlPaint paint;
1047 paint.setColor(DlColor::kRed());
1048 builder.DrawPaint(paint);
1049 builder.ClipRect(SkRect::MakeXYWH(100, 100, 200, 200));
1050 paint.setColor(DlColor::kBlue());
1051 builder.SaveLayer(nullptr, &paint);
1052 builder.Restore();
1053
1054 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1055 }

## ◆ TEST_P() [164/454]

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

Definition at line 1057 of file aiks_dl_basic_unittests.cc.

1057 {
1058 DisplayListBuilder builder;
1059 builder.Scale(GetContentScale().x, GetContentScale().y);
1060 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1061 builder.DrawImage(image, {10, 10}, {});
1062 builder.ClipRect(SkRect::MakeXYWH(100, 100, 200, 200));
1063
1064 DlPaint paint;
1065 paint.setBlendMode(DlBlendMode::kClear);
1066 builder.SaveLayer(nullptr, &paint);
1067 builder.Restore();
1068
1069 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1070 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [165/454]

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

Definition at line 1461 of file aiks_dl_basic_unittests.cc.

1461 {
1462 DisplayListBuilder builder;
1463
1464 builder.Scale(GetContentScale().x, GetContentScale().y);
1465 DlPaint paint;
1466 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1467
1468 DlPaint save_paint;
1469 save_paint.setColor(DlColor::kWhite());
1470 builder.DrawPaint(save_paint);
1471
1472 paint.setColor(DlColor::kBlue());
1473 for (int i = 0; i < 5; i++) {
1474 Scalar y = i * 125;
1475 Scalar y_radius = i * 15;
1476 for (int j = 0; j < 5; j++) {
1477 Scalar x = j * 125;
1478 Scalar x_radius = j * 15;
1479 builder.DrawRRect(
1480 SkRRect::MakeRectXY(SkRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f),
1481 x_radius, y_radius),
1482 paint);
1483 }
1484 }
1485
1486 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1487 }

## ◆ TEST_P() [166/454]

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 }

## ◆ TEST_P() [167/454]

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 }

## ◆ TEST_P() [168/454]

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 }

## ◆ TEST_P() [169/454]

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 }

## ◆ TEST_P() [170/454]

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

Definition at line 415 of file aiks_dl_basic_unittests.cc.

415 {
416 DisplayListBuilder builder;
417 builder.Scale(GetContentScale().x, GetContentScale().y);
418 DlPaint paint;
419 const int color_count = 3;
420 DlColor colors[color_count] = {
421 DlColor::kBlue(),
422 DlColor::kGreen(),
423 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
424 };
425
426 paint.setColor(DlColor::kWhite());
427 builder.DrawPaint(paint);
428
429 int c_index = 0;
430 int radius = 600;
431 while (radius > 0) {
432 paint.setColor(colors[(c_index++) % color_count]);
433 builder.DrawCircle({10, 10}, radius, paint);
434 if (radius > 30) {
435 radius -= 10;
436 } else {
437 radius -= 2;
438 }
439 }
440
441 DlColor gradient_colors[7] = {
442 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
443 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
444 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
445 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
446 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
447 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
448 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
449 };
450 DlScalar stops[7] = {
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 auto texture = CreateTextureForFixture("airplane.jpg",
460 /*enable_mipmapping=*/true);
461 auto image = DlImageImpeller::Make(texture);
462
463 paint.setColorSource(DlColorSource::MakeRadial(
464 {500, 600}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
465 builder.DrawCircle({500, 600}, 100, paint);
466
467 SkMatrix local_matrix = SkMatrix::Translate(700, 200);
468 DlImageColorSource image_source(
469 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
470 DlImageSampling::kNearestNeighbor, &local_matrix);
471 paint.setColorSource(&image_source);
472 builder.DrawCircle({800, 300}, 100, paint);
473
474 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
475 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [171/454]

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

Definition at line 544 of file aiks_dl_basic_unittests.cc.

544 {
545 DisplayListBuilder builder;
546 builder.Scale(GetContentScale().x, GetContentScale().y);
547 DlPaint paint;
548 const int color_count = 3;
549 DlColor colors[color_count] = {
550 DlColor::kBlue(),
551 DlColor::kGreen(),
552 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
553 };
554
555 paint.setColor(DlColor::kWhite());
556 builder.DrawPaint(paint);
557
558 int c_index = 0;
559 int long_radius = 600;
560 int short_radius = 600;
561 while (long_radius > 0 && short_radius > 0) {
562 paint.setColor(colors[(c_index++) % color_count]);
563 builder.DrawOval(SkRect::MakeXYWH(10 - long_radius, 10 - short_radius,
564 long_radius * 2, short_radius * 2),
565 paint);
566 builder.DrawOval(SkRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
567 short_radius * 2, long_radius * 2),
568 paint);
569 if (short_radius > 30) {
570 short_radius -= 10;
571 long_radius -= 5;
572 } else {
573 short_radius -= 2;
574 long_radius -= 1;
575 }
576 }
577
578 DlColor gradient_colors[7] = {
579 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
580 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
581 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
582 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
583 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
584 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
585 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
586 };
587 DlScalar stops[7] = {
588 0.0,
589 (1.0 / 6.0) * 1,
590 (1.0 / 6.0) * 2,
591 (1.0 / 6.0) * 3,
592 (1.0 / 6.0) * 4,
593 (1.0 / 6.0) * 5,
594 1.0,
595 };
596 auto texture = CreateTextureForFixture("airplane.jpg",
597 /*enable_mipmapping=*/true);
598 auto image = DlImageImpeller::Make(texture);
599
600 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
601
602 paint.setColorSource(DlColorSource::MakeRadial(
603 {300, 650}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
604 builder.DrawOval(SkRect::MakeXYWH(200, 625, 200, 50), paint);
605 builder.DrawOval(SkRect::MakeXYWH(275, 550, 50, 200), paint);
606
607 SkMatrix local_matrix = SkMatrix::Translate(610, 15);
608 DlImageColorSource image_source(
609 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
610 DlImageSampling::kNearestNeighbor, &local_matrix);
611 paint.setColorSource(&image_source);
612 builder.DrawOval(SkRect::MakeXYWH(610, 90, 200, 50), paint);
613 builder.DrawOval(SkRect::MakeXYWH(685, 15, 50, 200), paint);
614
615 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
616 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [172/454]

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

Definition at line 1193 of file aiks_dl_basic_unittests.cc.

1193 {
1194 DisplayListBuilder builder;
1195 builder.Scale(GetContentScale().x, GetContentScale().y);
1196
1197 DlPaint paint;
1198 const int color_count = 3;
1199 DlColor colors[color_count] = {
1200 DlColor::kBlue(),
1201 DlColor::kGreen(),
1202 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1203 };
1204
1205 paint.setColor(DlColor::kWhite());
1206 builder.DrawPaint(paint);
1207
1208 auto draw_rrect_as_path = [&builder](const SkRect& rect, Scalar x, Scalar y,
1209 const DlPaint& paint) {
1210 SkPath path;
1211 path.addRoundRect(rect, x, y);
1212 builder.DrawPath(path, paint);
1213 };
1214
1215 int c_index = 0;
1216 for (int i = 0; i < 4; i++) {
1217 for (int j = 0; j < 4; j++) {
1218 paint.setColor(colors[(c_index++) % color_count]);
1219 draw_rrect_as_path(SkRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1220 i * 5 + 10, j * 5 + 10, paint);
1221 }
1222 }
1223 paint.setColor(colors[(c_index++) % color_count]);
1224 draw_rrect_as_path(SkRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1225 paint.setColor(colors[(c_index++) % color_count]);
1226 draw_rrect_as_path(SkRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1227
1228 std::vector<DlColor> gradient_colors = {
1229 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1230 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1231 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1232 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1233 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1234 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1235 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1236 std::vector<Scalar> stops = {
1237 0.0,
1238 (1.0 / 6.0) * 1,
1239 (1.0 / 6.0) * 2,
1240 (1.0 / 6.0) * 3,
1241 (1.0 / 6.0) * 4,
1242 (1.0 / 6.0) * 5,
1243 1.0,
1244 };
1245 auto texture = DlImageImpeller::Make(
1246 CreateTextureForFixture("airplane.jpg",
1247 /*enable_mipmapping=*/true));
1248
1249 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1250 paint.setColorSource(DlColorSource::MakeRadial(
1251 /*center=*/{550, 550},
1252 /*radius=*/75,
1253 /*stop_count=*/gradient_colors.size(),
1254 /*colors=*/gradient_colors.data(),
1255 /*stops=*/stops.data(),
1256 /*tile_mode=*/DlTileMode::kMirror));
1257 for (int i = 1; i <= 10; i++) {
1258 int j = 11 - i;
1259 draw_rrect_as_path(SkRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1260 550 + i * 20, 550 + j * 20),
1261 i * 10, j * 10, paint);
1262 }
1263 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1264 paint.setColorSource(DlColorSource::MakeRadial(
1265 /*center=*/{200, 650},
1266 /*radius=*/75,
1267 /*stop_count=*/gradient_colors.size(),
1268 /*colors=*/gradient_colors.data(),
1269 /*stops=*/stops.data(),
1270 /*tile_mode=*/DlTileMode::kMirror));
1271 draw_rrect_as_path(SkRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1272 draw_rrect_as_path(SkRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1273
1274 auto matrix = SkMatrix::Translate(520, 20);
1275 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1276 paint.setColorSource(std::make_shared<DlImageColorSource>(
1277 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1278 DlImageSampling::kMipmapLinear, &matrix));
1279 for (int i = 1; i <= 10; i++) {
1280 int j = 11 - i;
1281 draw_rrect_as_path(SkRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1282 720 + i * 20, 220 + j * 20),
1283 i * 10, j * 10, paint);
1284 }
1285 matrix = SkMatrix::Translate(800, 300);
1286 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1287 paint.setColorSource(std::make_shared<DlImageColorSource>(
1288 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1289 DlImageSampling::kMipmapLinear, &matrix));
1290
1291 draw_rrect_as_path(SkRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1292 draw_rrect_as_path(SkRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1293
1294 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1295 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [173/454]

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

Definition at line 618 of file aiks_dl_basic_unittests.cc.

618 {
619 DisplayListBuilder builder;
620 builder.Scale(GetContentScale().x, GetContentScale().y);
621 DlPaint paint;
622 const int color_count = 3;
623 DlColor colors[color_count] = {
624 DlColor::kBlue(),
625 DlColor::kGreen(),
626 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
627 };
628
629 paint.setColor(DlColor::kWhite());
630 builder.DrawPaint(paint);
631
632 int c_index = 0;
633 for (int i = 0; i < 4; i++) {
634 for (int j = 0; j < 4; j++) {
635 paint.setColor(colors[(c_index++) % color_count]);
636 builder.DrawRRect(
637 SkRRect::MakeRectXY(
638 SkRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
639 i * 5 + 10, j * 5 + 10),
640 paint);
641 }
642 }
643 paint.setColor(colors[(c_index++) % color_count]);
644 builder.DrawRRect(
645 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 420, 380, 80), 40, 40), paint);
646 paint.setColor(colors[(c_index++) % color_count]);
647 builder.DrawRRect(
648 SkRRect::MakeRectXY(SkRect::MakeXYWH(410, 20, 80, 380), 40, 40), paint);
649
650 DlColor gradient_colors[7] = {
651 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
652 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
653 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
654 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
655 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
656 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
657 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
658 };
659 DlScalar stops[7] = {
660 0.0,
661 (1.0 / 6.0) * 1,
662 (1.0 / 6.0) * 2,
663 (1.0 / 6.0) * 3,
664 (1.0 / 6.0) * 4,
665 (1.0 / 6.0) * 5,
666 1.0,
667 };
668 auto texture = CreateTextureForFixture("airplane.jpg",
669 /*enable_mipmapping=*/true);
670 auto image = DlImageImpeller::Make(texture);
671
672 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
673 paint.setColorSource(DlColorSource::MakeRadial(
674 {550, 550}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
675 for (int i = 1; i <= 10; i++) {
676 int j = 11 - i;
677 builder.DrawRRect(
678 SkRRect::MakeRectXY(SkRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
679 550 + i * 20, 550 + j * 20),
680 i * 10, j * 10),
681 paint);
682 }
683
684 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
685 paint.setColorSource(DlColorSource::MakeRadial(
686 {200, 650}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
687 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
688 builder.DrawRRect(
689 SkRRect::MakeRectXY(SkRect::MakeLTRB(100, 610, 300, 690), 40, 40), paint);
690 builder.DrawRRect(
691 SkRRect::MakeRectXY(SkRect::MakeLTRB(160, 550, 240, 750), 40, 40), paint);
692
693 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
694 SkMatrix local_matrix = SkMatrix::Translate(520, 20);
695 DlImageColorSource image_source(
696 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
697 DlImageSampling::kNearestNeighbor, &local_matrix);
698 paint.setColorSource(&image_source);
699 for (int i = 1; i <= 10; i++) {
700 int j = 11 - i;
701 builder.DrawRRect(
702 SkRRect::MakeRectXY(SkRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
703 720 + i * 20, 220 + j * 20),
704 i * 10, j * 10),
705 paint);
706 }
707
708 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
709 local_matrix = SkMatrix::Translate(800, 300);
710 DlImageColorSource image_source2(
711 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
712 DlImageSampling::kNearestNeighbor, &local_matrix);
713 paint.setColorSource(&image_source2);
714 builder.DrawRRect(
715 SkRRect::MakeRectXY(SkRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
716 paint);
717 builder.DrawRRect(
718 SkRRect::MakeRectXY(SkRect::MakeLTRB(860, 350, 940, 550), 40, 40), paint);
719
720 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
721 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [174/454]

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

Definition at line 733 of file aiks_dl_blend_unittests.cc.

733 {
734 auto texture = CreateTextureForFixture("airplane.jpg",
735 /*enable_mipmapping=*/true);
736
737 DisplayListBuilder builder;
738 builder.Rotate(30);
739
740 DlPaint image_paint;
741 image_paint.setColorFilter(DlBlendColorFilter::Make(
742 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
743 DlBlendMode::kColorDodge));
744
745 builder.DrawImage(DlImageImpeller::Make(texture), {200, 200},
746 DlImageSampling::kMipmapLinear, &image_paint);
747
748 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
749 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [175/454]

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

Definition at line 468 of file aiks_dl_blend_unittests.cc.

468 {
469 DisplayListBuilder builder;
470
471 DlPaint save_paint;
472 save_paint.setColorFilter(
473 DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kColorDodge));
474 builder.SaveLayer(nullptr, &save_paint);
475
476 builder.Translate(500, 300);
477 builder.Rotate(120);
478
479 DlPaint paint;
480 paint.setColor(DlColor::kBlue());
481 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), paint);
482
483 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
484 }

## ◆ TEST_P() [176/454]

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

Definition at line 715 of file aiks_dl_blend_unittests.cc.

715 {
716 auto texture = CreateTextureForFixture("airplane.jpg",
717 /*enable_mipmapping=*/true);
718
719 DisplayListBuilder builder;
720 builder.Rotate(30);
721
722 DlPaint image_paint;
723 image_paint.setColorFilter(DlBlendColorFilter::Make(
724 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
725 DlBlendMode::kSrcIn));
726
727 builder.DrawImage(DlImageImpeller::Make(texture), {200, 200},
728 DlImageSampling::kMipmapLinear, &image_paint);
729
730 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
731 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [177/454]

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

Definition at line 1106 of file aiks_dl_basic_unittests.cc.

1106 {
1107 PixelFormat pixel_format =
1108 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1109 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1110 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1111 << "pixel format: " << PixelFormatToString(pixel_format);
1112 }

References impeller::kB8G8R8A8UNormInt, impeller::kR8G8B8A8UNormInt, and impeller::PixelFormatToString().

## ◆ TEST_P() [178/454]

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

Definition at line 1101 of file aiks_dl_basic_unittests.cc.

1101 {
1102 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1103 PixelFormat::kB10G10R10A10XR);
1104 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [179/454]

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

Definition at line 751 of file aiks_dl_blend_unittests.cc.

751 {
752 auto texture = CreateTextureForFixture("airplane.jpg",
753 /*enable_mipmapping=*/true);
754
755 // Draw with an advanced blend that can use FramebufferBlendContents and
756 // verify that the scale transform is correctly applied to the image.
757 DisplayListBuilder builder;
758
759 DlPaint paint;
760 paint.setColor(
761 DlColor::RGBA(169.0f / 255.0f, 169.0f / 255.0f, 169.0f / 255.0f, 1.0f));
762 builder.DrawPaint(paint);
763 builder.Scale(0.4, 0.4);
764
765 DlPaint image_paint;
766 image_paint.setBlendMode(DlBlendMode::kMultiply);
767
768 builder.DrawImage(DlImageImpeller::Make(texture), {20, 20},
769 DlImageSampling::kMipmapLinear, &image_paint);
770
771 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
772 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [180/454]

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 }

## ◆ TEST_P() [181/454]

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

Definition at line 749 of file aiks_dl_blur_unittests.cc.

749 {
750 // This test is for checking out how stable rendering is when content is
751 // translated underneath a blur. Animating under a blur can cause
752 // *shimmering* to happen as a result of pixel alignment.
753 // See also: https://github.com/flutter/flutter/issues/140193
754 auto boston =
755 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
756 ASSERT_TRUE(boston);
757 int64_t count = 0;
758 Scalar sigma = 20.0;
759 Scalar freq = 0.1;
760 Scalar amp = 50.0;
761 auto callback = [&]() -> sk_sp<DisplayList> {
762 if (AiksTest::ImGuiBegin("Controls", nullptr,
763 ImGuiWindowFlags_AlwaysAutoResize)) {
764 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
765 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
766 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
767 ImGui::End();
768 }
769
770 DisplayListBuilder builder;
771 builder.Scale(GetContentScale().x, GetContentScale().y);
772 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
773 builder.DrawImage(
774 DlImageImpeller::Make(boston),
775 SkPoint::Make(1024 / 2 - boston->GetSize().width / 2,
776 (768 / 2 - boston->GetSize().height / 2) + y),
777 DlImageSampling::kMipmapLinear);
778 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
779 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
780 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
781
782 builder.ClipRect(
783 SkRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
784 builder.ClipRect(SkRect::MakeLTRB(100, 100, 900, 700));
785
786 DlPaint paint;
787 paint.setBlendMode(DlBlendMode::kSrc);
788
789 auto backdrop_filter =
790 DlBlurImageFilter::Make(sigma, sigma, DlTileMode::kClamp);
791 builder.SaveLayer(nullptr, &paint, backdrop_filter.get());
792 count += 1;
793 return builder.Build();
794 };
795 ASSERT_TRUE(OpenPlaygroundHere(callback));
796 }

References impeller::DrawPlaygroundLine(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and impeller::Color::Red().

## ◆ TEST_P() [182/454]

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

Definition at line 720 of file aiks_dl_blur_unittests.cc.

720 {
721 DisplayListBuilder builder;
722
723 builder.Scale(GetContentScale().x, GetContentScale().y);
724 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
725 builder.DrawImageRect(
726 DlImageImpeller::Make(boston),
727 SkRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
728 SkRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
729 DlImageSampling::kNearestNeighbor);
730
731 DlPaint paint;
732 paint.setColor(DlColor::kMagenta());
733
734 SkRRect rrect = SkRRect::MakeRectXY(
735 SkRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
736 builder.DrawRRect(rrect, paint);
737 builder.ClipRect(SkRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
738
739 DlPaint save_paint;
740 save_paint.setBlendMode(DlBlendMode::kSrc);
741
742 auto backdrop_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kClamp);
743 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
744
745 builder.Restore();
746 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
747 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [183/454]

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

Definition at line 692 of file aiks_dl_blur_unittests.cc.

692 {
693 DisplayListBuilder builder;
694
695 DlPaint paint;
696 builder.Scale(GetContentScale().x, GetContentScale().y);
697
698 paint.setColor(DlColor::kLimeGreen());
699 SkRRect rrect = SkRRect::MakeRectXY(
700 SkRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
701 builder.DrawRRect(rrect, paint);
702
703 paint.setColor(DlColor::kMagenta());
704 rrect = SkRRect::MakeRectXY(
705 SkRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
706 builder.DrawRRect(rrect, paint);
707 builder.ClipRect(SkRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
708
709 DlPaint save_paint;
710 save_paint.setBlendMode(DlBlendMode::kSrc);
711
712 auto backdrop_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kClamp);
713
714 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
715 builder.Restore();
716
717 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
718 }

## ◆ TEST_P() [184/454]

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

Definition at line 1238 of file aiks_dl_blur_unittests.cc.

1238 {
1239 AiksContext renderer(GetContext(), nullptr);
1240 for (int32_t i = 1; i < 5; ++i) {
1241 DisplayListBuilder builder;
1242
1243 ISize clip_size = ISize(i, i);
1244 builder.Save();
1245 builder.ClipRect(
1246 SkRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1247
1248 DlPaint paint;
1249 paint.setColor(DlColor::kGreen());
1250 auto blur_filter = DlBlurImageFilter::Make(0.1, 0.1, DlTileMode::kDecal);
1251 paint.setImageFilter(blur_filter);
1252
1253 builder.DrawCircle({400, 400}, 200, paint);
1254 builder.Restore();
1255
1256 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1257 EXPECT_TRUE(image) << " length " << i;
1258 }
1259 }

References impeller::DisplayListToTexture(), impeller::TSize< T >::height, and impeller::TSize< T >::width.

## ◆ TEST_P() [185/454]

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

Definition at line 996 of file aiks_dl_blur_unittests.cc.

996 {
997 DisplayListBuilder builder;
998
999 builder.Scale(GetContentScale().x, GetContentScale().y);
1000 builder.Scale(0.5, 0.5);
1001
1002 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1003 builder.DrawImage(DlImageImpeller::Make(boston), {100, 100}, {});
1004
1005 DlPaint paint;
1006 paint.setBlendMode(DlBlendMode::kSrc);
1007
1008 auto backdrop_filter = DlBlurImageFilter::Make(50, 0, DlTileMode::kClamp);
1009 builder.SaveLayer(nullptr, &paint, backdrop_filter.get());
1010 builder.Restore();
1011 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1012 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [186/454]

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

Definition at line 1018 of file aiks_dl_blur_unittests.cc.

1018 {
1019 DisplayListBuilder builder;
1020
1021 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1022 Rect bounds =
1023 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1024
1025 DlPaint paint;
1026 paint.setImageFilter(DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal));
1027
1028 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1029 Vector2 clip_size = {150, 75};
1030 Vector2 center = Vector2(1024, 768) / 2;
1031 builder.Scale(GetContentScale().x, GetContentScale().y);
1032
1033 auto clip_bounds =
1034 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1035 builder.ClipRect(SkRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1036 clip_bounds.GetRight(),
1037 clip_bounds.GetBottom()));
1038 builder.Translate(center.x, center.y);
1039 builder.Scale(0.6, 0.6);
1040 builder.Rotate(25);
1041
1042 auto dst_rect = bounds.Shift(-image_center);
1043 builder.DrawImageRect(
1044 DlImageImpeller::Make(boston), /*src=*/
1045 SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1046 bounds.GetBottom()),
1047 /*dst=*/
1048 SkRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1049 dst_rect.GetRight(), dst_rect.GetBottom()),
1050 DlImageSampling::kMipmapLinear, &paint);
1051
1052 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1053 }

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< T >::Shift(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [187/454]

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

Definition at line 941 of file aiks_dl_blur_unittests.cc.

941 {
942 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
943
944 auto callback = [&]() -> sk_sp<DisplayList> {
945 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
946 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
947 DlTileMode::kMirror, DlTileMode::kDecal};
948
949 static float rotation = 0;
950 static float scale = 0.6;
951 static int selected_tile_mode = 3;
952
953 if (AiksTest::ImGuiBegin("Controls", nullptr,
954 ImGuiWindowFlags_AlwaysAutoResize)) {
955 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
956 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
957 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
958 sizeof(tile_mode_names) / sizeof(char*));
959 ImGui::End();
960 }
961
962 DisplayListBuilder builder;
963 Rect bounds =
964 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
965 Vector2 image_center = Vector2(bounds.GetSize() / 2);
966 DlPaint paint;
967 paint.setImageFilter(
968 DlBlurImageFilter::Make(20, 20, tile_modes[selected_tile_mode]));
969
970 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
971 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
972 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
973 Vector2 center = Vector2(1024, 768) / 2;
974
975 builder.Scale(GetContentScale().x, GetContentScale().y);
976 builder.ClipRect(
977 SkRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
978 builder.Translate(center.x, center.y);
979 builder.Scale(scale, scale);
980 builder.Rotate(rotation);
981
982 SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
983 bounds.GetRight(), bounds.GetBottom());
984 Rect dest = bounds.Shift(-image_center);
985 SkRect sk_dst = SkRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
986 dest.GetRight(), dest.GetBottom());
987 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
988 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
989 &paint);
990 return builder.Build();
991 };
992
993 ASSERT_TRUE(OpenPlaygroundHere(callback));
994 }

References impeller::DrawPlaygroundLine(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::TPoint< T >::Rotate(), scale, impeller::TRect< T >::Shift(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [188/454]

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

Definition at line 1055 of file aiks_dl_blur_unittests.cc.

1055 {
1056 auto callback = [&]() -> sk_sp<DisplayList> {
1057 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1058 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1059 DlTileMode::kMirror, DlTileMode::kDecal};
1060
1061 static float rotation = 45;
1062 static float scale = 0.6;
1063 static int selected_tile_mode = 3;
1064
1065 if (AiksTest::ImGuiBegin("Controls", nullptr,
1066 ImGuiWindowFlags_AlwaysAutoResize)) {
1067 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1068 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1069 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1070 sizeof(tile_mode_names) / sizeof(char*));
1071 ImGui::End();
1072 }
1073
1074 DisplayListBuilder builder;
1075
1076 DlPaint paint;
1077 paint.setColor(DlColor::kGreen());
1078 paint.setImageFilter(
1079 DlBlurImageFilter::Make(50, 0, tile_modes[selected_tile_mode]));
1080
1081 Vector2 center = Vector2(1024, 768) / 2;
1082 builder.Scale(GetContentScale().x, GetContentScale().y);
1083 builder.Translate(center.x, center.y);
1084 builder.Scale(scale, scale);
1085 builder.Rotate(rotation);
1086
1087 SkRRect rrect =
1088 SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
1089 builder.DrawRRect(rrect, paint);
1090 return builder.Build();
1091 };
1092
1093 ASSERT_TRUE(OpenPlaygroundHere(callback));
1094 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::TPoint< T >::Rotate(), scale, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [189/454]

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

Definition at line 908 of file aiks_dl_blur_unittests.cc.

908 {
909 DisplayListBuilder builder;
910 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
911 Rect bounds =
912 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
913 Vector2 image_center = Vector2(bounds.GetSize() / 2);
914
915 DlPaint paint;
916 paint.setImageFilter(DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal));
917
918 Vector2 clip_size = {150, 75};
919 Vector2 center = Vector2(1024, 768) / 2;
920 builder.Scale(GetContentScale().x, GetContentScale().y);
921
922 auto rect =
923 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
924 builder.ClipRect(SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
925 rect.GetRight(), rect.GetBottom()));
926 builder.Translate(center.x, center.y);
927 builder.Scale(0.6, 0.6);
928
929 SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
930 bounds.GetRight(), bounds.GetBottom());
931 Rect dest = bounds.Shift(-image_center);
932 SkRect sk_dst = SkRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
933 dest.GetRight(), dest.GetBottom());
934 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
935 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
936 &paint);
937
938 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
939 }

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< T >::Shift(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [190/454]

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

Definition at line 1213 of file aiks_dl_blur_unittests.cc.

1213 {
1214 AiksContext renderer(GetContext(), nullptr);
1215
1216 for (int32_t i = 1; i < 5; ++i) {
1217 DisplayListBuilder builder;
1218 Scalar fi = i;
1219 SkPath path;
1220 path.moveTo(100, 100);
1221 path.lineTo(100 + fi, 100 + fi);
1222
1223 DlPaint paint;
1224 paint.setColor(DlColor::kChartreuse());
1225 auto blur_filter = DlBlurImageFilter::Make(0.1, 0.1, DlTileMode::kClamp);
1226 paint.setImageFilter(blur_filter);
1227
1228 builder.DrawPath(path, paint);
1229
1230 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1231 EXPECT_TRUE(image) << " length " << i;
1232 }
1233 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [191/454]

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

Definition at line 547 of file aiks_dl_blur_unittests.cc.

547 {
548 DisplayListBuilder builder;
549 builder.Scale(GetContentScale().x, GetContentScale().y);
550
551 DlPaint paint;
552 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
553 builder.DrawPaint(paint);
554
555 paint.setColor(DlColor::kGreen());
556 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
557
558 SkPath path;
559 path.moveTo(200, 200);
560 path.lineTo(300, 400);
561 path.lineTo(100, 400);
562 path.close();
563
564 builder.DrawPath(path, paint);
565
566 // Draw another thing to make sure the clip area is reset.
567 DlPaint red;
568 red.setColor(DlColor::kRed());
569 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
570
571 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
572 }

## ◆ TEST_P() [192/454]

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

Definition at line 798 of file aiks_dl_blur_unittests.cc.

798 {
799 DisplayListBuilder builder;
800
801 builder.Scale(GetContentScale().x, GetContentScale().y);
802
803 DlPaint paint;
804 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
805 builder.DrawPaint(paint);
806
807 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
808 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
809 std::vector<Scalar> stops = {0.0, 1.0};
810
811 paint = DlPaint{};
812 paint.setColorSource(DlColorSource::MakeLinear(
813 /*start_point=*/{0, 0},
814 /*end_point=*/{200, 200},
815 /*stop_count=*/colors.size(),
816 /*colors=*/colors.data(),
817 /*stops=*/stops.data(),
818 /*tile_mode=*/DlTileMode::kMirror));
819 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
820
821 SkPath path;
822 path.moveTo(200, 200);
823 path.lineTo(300, 400);
824 path.lineTo(100, 400);
825 path.close();
826 builder.DrawPath(path, paint);
827
828 // Draw another thing to make sure the clip area is reset.
829 DlPaint red;
830 red.setColor(DlColor::kRed());
831 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
832
833 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
834 }

## ◆ TEST_P() [193/454]

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

Definition at line 574 of file aiks_dl_blur_unittests.cc.

574 {
575 DisplayListBuilder builder;
576 builder.Scale(GetContentScale().x, GetContentScale().y);
577
578 DlPaint paint;
579 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
580 builder.DrawPaint(paint);
581
582 paint.setColor(DlColor::kGreen());
583 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
584
585 SkPath path;
586 path.moveTo(200, 200);
587 path.lineTo(300, 400);
588 path.lineTo(100, 400);
589 path.close();
590
591 builder.DrawPath(path, paint);
592
593 // Draw another thing to make sure the clip area is reset.
594 DlPaint red;
595 red.setColor(DlColor::kRed());
596 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
597
598 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
599 }

## ◆ TEST_P() [194/454]

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

Definition at line 872 of file aiks_dl_blur_unittests.cc.

872 {
873 DisplayListBuilder builder;
874 builder.Scale(GetContentScale().x, GetContentScale().y);
875
876 DlPaint paint;
877 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
878 builder.DrawPaint(paint);
879
880 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
881 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
882 std::vector<Scalar> stops = {0.0, 1.0};
883
884 paint = DlPaint{};
885 paint.setColorSource(DlColorSource::MakeLinear(
886 /*start_point=*/{0, 0},
887 /*end_point=*/{200, 200},
888 /*stop_count=*/colors.size(),
889 /*colors=*/colors.data(),
890 /*stops=*/stops.data(),
891 /*tile_mode=*/DlTileMode::kMirror));
892 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
893
894 SkPath path;
895 path.moveTo(200, 200);
896 path.lineTo(300, 400);
897 path.lineTo(100, 400);
898 path.close();
899 builder.DrawPath(path, paint);
900
901 // Draw another thing to make sure the clip area is reset.
902 DlPaint red;
903 red.setColor(DlColor::kRed());
904 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
905 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
906 }

## ◆ TEST_P() [195/454]

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

Definition at line 601 of file aiks_dl_blur_unittests.cc.

601 {
602 DisplayListBuilder builder;
603 builder.Scale(GetContentScale().x, GetContentScale().y);
604
605 DlPaint paint;
606 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
607 builder.DrawPaint(paint);
608
609 paint.setColor(DlColor::kGreen());
610 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
611
612 SkPath path;
613 path.moveTo(200, 200);
614 path.lineTo(300, 400);
615 path.lineTo(100, 400);
616 path.close();
617
618 builder.DrawPath(path, paint);
619
620 // Draw another thing to make sure the clip area is reset.
621 DlPaint red;
622 red.setColor(DlColor::kRed());
623 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
624
625 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
626 }

## ◆ TEST_P() [196/454]

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

Definition at line 836 of file aiks_dl_blur_unittests.cc.

836 {
837 DisplayListBuilder builder;
838 builder.Scale(GetContentScale().x, GetContentScale().y);
839
840 DlPaint paint;
841 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
842 builder.DrawPaint(paint);
843
844 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
845 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
846 std::vector<Scalar> stops = {0.0, 1.0};
847
848 paint = DlPaint{};
849 paint.setColorSource(DlColorSource::MakeLinear(
850 /*start_point=*/{0, 0},
851 /*end_point=*/{200, 200},
852 /*stop_count=*/colors.size(),
853 /*colors=*/colors.data(),
854 /*stops=*/stops.data(),
855 /*tile_mode=*/DlTileMode::kMirror));
856 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
857
858 SkPath path;
859 path.moveTo(200, 200);
860 path.lineTo(300, 400);
861 path.lineTo(100, 400);
862 path.close();
863 builder.DrawPath(path, paint);
864
865 // Draw another thing to make sure the clip area is reset.
866 DlPaint red;
867 red.setColor(DlColor::kRed());
868 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
869 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
870 }

## ◆ TEST_P() [197/454]

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

Definition at line 1160 of file aiks_dl_blur_unittests.cc.

1160 {
1161 if (GetParam() != PlaygroundBackend::kMetal) {
1162 GTEST_SKIP()
1163 << "This backend doesn't yet support setting device capabilities.";
1164 }
1165 if (!WillRenderSomething()) {
1166 // Sometimes these tests are run without playgrounds enabled which is
1167 // pointless for this test since we are asserting that
1168 // `SupportsDecalSamplerAddressMode` is called.
1169 GTEST_SKIP() << "This test requires playgrounds.";
1170 }
1171
1172 std::shared_ptr<const Capabilities> old_capabilities =
1173 GetContext()->GetCapabilities();
1174 auto mock_capabilities = std::make_shared<MockCapabilities>();
1175 EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode())
1176 .Times(::testing::AtLeast(1))
1177 .WillRepeatedly(::testing::Return(false));
1178 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
1179 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
1180 FLT_FORWARD(mock_capabilities, old_capabilities,
1181 GetDefaultDepthStencilFormat);
1182 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
1183 FLT_FORWARD(mock_capabilities, old_capabilities,
1184 SupportsImplicitResolvingMSAA);
1185 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
1186 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch);
1187 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
1188 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
1189 FLT_FORWARD(mock_capabilities, old_capabilities,
1190 SupportsTextureToTextureBlits);
1191 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
1192 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTriangleFan);
1193 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
1194
1195 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
1196
1197 DisplayListBuilder builder;
1198 builder.Scale(GetContentScale().x * 0.5, GetContentScale().y * 0.5);
1199
1200 DlPaint paint;
1201 paint.setColor(DlColor::kBlack());
1202 builder.DrawPaint(paint);
1203
1204 auto blur_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal);
1205 paint.setImageFilter(blur_filter);
1206 builder.DrawImage(texture, SkPoint::Make(200, 200), {}, &paint);
1207 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1208 }

References impeller::kMetal, and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [198/454]

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

Definition at line 104 of file aiks_dl_blur_unittests.cc.

104 {
105 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
106 GetContentScale(), /*sigma=*/10, DlBlurStyle::kNormal)));
107 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [199/454]

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

Definition at line 119 of file aiks_dl_blur_unittests.cc.

119 {
120 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
121 GetContentScale(), /*sigma=*/10, DlBlurStyle::kInner)));
122 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [200/454]

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

Definition at line 114 of file aiks_dl_blur_unittests.cc.

114 {
115 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
116 GetContentScale(), /*sigma=*/10, DlBlurStyle::kOuter)));
117 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [201/454]

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

Definition at line 109 of file aiks_dl_blur_unittests.cc.

109 {
110 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
111 GetContentScale(), /*sigma=*/0, DlBlurStyle::kNormal)));
112 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [202/454]

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

Definition at line 124 of file aiks_dl_blur_unittests.cc.

124 {
125 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
126 GetContentScale(), /*sigma=*/10, DlBlurStyle::kSolid)));
127 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [203/454]

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(), scale, impeller::Color::ToARGB(), impeller::skia_conversions::ToMatrix(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [204/454]

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

Definition at line 887 of file aiks_dl_basic_unittests.cc.

887 {
888 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
889
890 DisplayListBuilder builder;
891 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
892
893 DlPaint paint;
894 paint.setColor(DlColor::kWhite());
895 builder.DrawPaint(paint);
896
897 // Translation
898 {
899 SkMatrix matrix = SkMatrix::Translate(50, 50);
900 DlPaint paint;
901 paint.setColorSource(std::make_shared<DlImageColorSource>(
902 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
903 DlImageSampling::kNearestNeighbor, &matrix));
904
905 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
906 }
907
908 // Rotation/skew
909 {
910 builder.Save();
911 builder.Rotate(45);
912 DlPaint paint;
913
914 Matrix impeller_matrix(1, -1, 0, 0, //
915 1, 1, 0, 0, //
916 0, 0, 1, 0, //
917 0, 0, 0, 1);
918 SkMatrix matrix = SkM44::ColMajor(impeller_matrix.m).asM33();
919 paint.setColorSource(std::make_shared<DlImageColorSource>(
920 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
921 DlImageSampling::kNearestNeighbor, &matrix));
922 builder.DrawRect(SkRect::MakeLTRB(100, 0, 200, 100), paint);
923 builder.Restore();
924 }
925
926 // Scale
927 {
928 builder.Translate(100, 0);
929 builder.Scale(100, 100);
930 DlPaint paint;
931
932 SkMatrix matrix = SkMatrix::Scale(0.005, 0.005);
933 paint.setColorSource(std::make_shared<DlImageColorSource>(
934 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
935 DlImageSampling::kNearestNeighbor, &matrix));
936
937 builder.DrawRect(SkRect::MakeLTRB(0, 0, 1, 1), paint);
938 }
939
940 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
941 }

References impeller::Matrix::m, and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [205/454]

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

Definition at line 651 of file aiks_dl_unittests.cc.

651 {
652 DisplayListBuilder builder;
653 builder.Scale(GetContentScale().x, GetContentScale().y);
654
655 auto test = [&builder](const std::shared_ptr<const DlImageFilter>& filter) {
656 auto DrawLine = [&builder](const SkPoint& p0, const SkPoint& p1,
657 const DlPaint& p) {
658 DlPaint paint = p;
659 paint.setDrawStyle(DlDrawStyle::kStroke);
660 builder.DrawPath(SkPath::Line(p0, p1), paint);
661 };
662 // Registration marks for the edge of the SaveLayer
663 DlPaint paint;
664 paint.setColor(DlColor::kWhite());
665 DrawLine(SkPoint::Make(75, 100), SkPoint::Make(225, 100), paint);
666 DrawLine(SkPoint::Make(75, 200), SkPoint::Make(225, 200), paint);
667 DrawLine(SkPoint::Make(100, 75), SkPoint::Make(100, 225), paint);
668 DrawLine(SkPoint::Make(200, 75), SkPoint::Make(200, 225), paint);
669
670 DlPaint save_paint;
671 save_paint.setImageFilter(filter);
672 SkRect bounds = SkRect::MakeLTRB(100, 100, 200, 200);
673 builder.SaveLayer(&bounds, &save_paint);
674
675 {
676 // DrawPaint to verify correct behavior when the contents are unbounded.
677 DlPaint paint;
678 paint.setColor(DlColor::kYellow());
679 builder.DrawPaint(paint);
680
681 // Contrasting rectangle to see interior blurring
682 paint.setColor(DlColor::kBlue());
683 builder.DrawRect(SkRect::MakeLTRB(125, 125, 175, 175), paint);
684 }
685 builder.Restore();
686 };
687
688 test(std::make_shared<DlBlurImageFilter>(10.0, 10.0, DlTileMode::kDecal));
689
690 builder.Translate(200.0, 0.0);
691
692 test(std::make_shared<DlDilateImageFilter>(10.0, 10.0));
693
694 builder.Translate(200.0, 0.0);
695
696 test(std::make_shared<DlErodeImageFilter>(10.0, 10.0));
697
698 builder.Translate(-400.0, 200.0);
699
700 SkMatrix sk_matrix = SkMatrix::RotateDeg(10);
701
702 auto rotate_filter = std::make_shared<DlMatrixImageFilter>(
703 sk_matrix, DlImageSampling::kLinear);
704 test(rotate_filter);
705
706 builder.Translate(200.0, 0.0);
707
708 const float m[20] = {
709 0, 1, 0, 0, 0, //
710 0, 0, 1, 0, 0, //
711 1, 0, 0, 0, 0, //
712 0, 0, 0, 1, 0 //
713 };
714 auto rgb_swap_filter = std::make_shared<DlColorFilterImageFilter>(
715 std::make_shared<DlMatrixColorFilter>(m));
716 test(rgb_swap_filter);
717
718 builder.Translate(200.0, 0.0);
719
720 test(DlComposeImageFilter::Make(rotate_filter, rgb_swap_filter));
721
722 builder.Translate(-400.0, 200.0);
723
724 test(std::make_shared<DlLocalMatrixImageFilter>(
725 SkMatrix::Translate(25.0, 25.0), rotate_filter));
726
727 builder.Translate(200.0, 0.0);
728
729 test(std::make_shared<DlLocalMatrixImageFilter>(
730 SkMatrix::Translate(25.0, 25.0), rgb_swap_filter));
731
732 builder.Translate(200.0, 0.0);
733
734 test(std::make_shared<DlLocalMatrixImageFilter>(
735 SkMatrix::Translate(25.0, 25.0),
736 DlComposeImageFilter::Make(rotate_filter, rgb_swap_filter)));
737
738 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
739 }

## ◆ TEST_P() [206/454]

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

Definition at line 216 of file aiks_dl_unittests.cc.

216 {
217 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
218 builder.Scale(GetContentScale().x, GetContentScale().y);
219
220 DlPaint save_paint;
221 save_paint.setImageFilter(
222 DlBlurImageFilter::Make(10.0, 10.0, DlTileMode::kDecal));
223 builder.SaveLayer(nullptr, &save_paint);
224
225 {
226 // DrawPaint to verify correct behavior when the contents are unbounded.
227 DlPaint draw_paint;
228 draw_paint.setColor(DlColor::kYellow());
229 builder.DrawPaint(draw_paint);
230
231 // Contrasting rectangle to see interior blurring
232 DlPaint draw_rect;
233 draw_rect.setColor(DlColor::kBlue());
234 builder.DrawRect(SkRect::MakeLTRB(125, 125, 175, 175), draw_rect);
235 }
236 builder.Restore();
237
238 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
239 }

## ◆ TEST_P() [207/454]

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

Definition at line 102 of file aiks_dl_unittests.cc.

102 {
103 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
104
105 DlPaint paint;
106 paint.setColorFilter(DlLinearToSrgbGammaColorFilter::kInstance);
107 builder.SaveLayer(nullptr, &paint);
108
109 builder.Translate(500, 300);
110 builder.Rotate(120); // 120 deg.
111
112 DlPaint draw_paint;
113 draw_paint.setColor(DlColor::kBlue());
114 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
115
116 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
117 }

## ◆ TEST_P() [208/454]

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

Definition at line 657 of file aiks_dl_blur_unittests.cc.

657 {
658 Scalar sigma = 70;
659 auto callback = [&]() -> sk_sp<DisplayList> {
660 if (AiksTest::ImGuiBegin("Controls", nullptr,
661 ImGuiWindowFlags_AlwaysAutoResize)) {
662 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
663 ImGui::End();
664 }
665
666 DisplayListBuilder builder;
667 builder.Scale(GetContentScale().x, GetContentScale().y);
668
669 DlPaint paint;
670 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
671 builder.DrawPaint(paint);
672
673 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
674
675 builder.Transform(SkMatrix::Translate(100, 100) *
676 SkMatrix::Scale(0.5, 0.5));
677
678 paint.setColorSource(std::make_shared<DlImageColorSource>(
679 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
680 DlImageSampling::kMipmapLinear));
681 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
682
683 builder.DrawRect(SkRect::MakeXYWH(0, 0, boston->GetSize().width,
684 boston->GetSize().height),
685 paint);
686
687 return builder.Build();
688 };
689 ASSERT_TRUE(OpenPlaygroundHere(callback));
690 }

References impeller::AiksPlayground::ImGuiBegin(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [209/454]

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

Definition at line 628 of file aiks_dl_blur_unittests.cc.

628 {
629 Scalar sigma = 30;
630 auto callback = [&]() -> sk_sp<DisplayList> {
631 if (AiksTest::ImGuiBegin("Controls", nullptr,
632 ImGuiWindowFlags_AlwaysAutoResize)) {
633 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
634 ImGui::End();
635 }
636
637 DisplayListBuilder builder;
638 builder.Scale(GetContentScale().x, GetContentScale().y);
639
640 DlPaint paint;
641 paint.setColor(DlColor::kGreen());
642 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
643
644 builder.DrawImage(
645 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
646 {200, 200}, DlImageSampling::kNearestNeighbor, &paint);
647
648 DlPaint red;
649 red.setColor(DlColor::kRed());
650 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
651
652 return builder.Build();
653 };
654 ASSERT_TRUE(OpenPlaygroundHere(callback));
655 }

References impeller::AiksPlayground::ImGuiBegin(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [210/454]

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

Definition at line 381 of file aiks_dl_blur_unittests.cc.

381 {
382 DisplayListBuilder builder;
383
384 DlPaint paint;
385 paint.setColor(DlColor::kBlue());
386 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 0));
387
388 builder.DrawCircle({300, 300}, 200, paint);
389 builder.DrawRect(SkRect::MakeLTRB(100, 300, 500, 600), paint);
390
391 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
392 }

## ◆ TEST_P() [211/454]

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

Definition at line 1515 of file aiks_dl_basic_unittests.cc.

1515 {
1516 if (GetBackend() == PlaygroundBackend::kVulkan) {
1517 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
1518 }
1519 DisplayListBuilder builder(SkRect::MakeSize(SkSize::Make(1000, 1000)));
1520
1521 auto filter = DlMatrixImageFilter::Make(SkMatrix::Scale(0.001, 0.001),
1522 DlImageSampling::kLinear);
1523
1524 DlPaint paint;
1525 paint.setImageFilter(filter);
1526 builder.SaveLayer(nullptr, &paint);
1527 {
1528 DlPaint paint;
1529 paint.setColor(DlColor::kRed());
1530 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100000, 100000), paint);
1531 }
1532 builder.Restore();
1533
1534 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1535 }

References impeller::kVulkan.

## ◆ TEST_P() [212/454]

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

Definition at line 741 of file aiks_dl_unittests.cc.

741 {
742 DisplayListBuilder builder;
743
744 DlPaint paint;
745 paint.setColor(DlColor::kBlack());
746 builder.DrawPaint(paint);
747 builder.SaveLayer(nullptr, nullptr);
748 {
749 DlPaint paint;
750 paint.setColor(DlColor::kGreen().withAlpha(0.5 * 255));
751 paint.setBlendMode(DlBlendMode::kPlus);
752
753 DlPaint rect_paint;
754 rect_paint.setColor(DlColor::kRed());
755 rect_paint.setStrokeWidth(4);
756 rect_paint.setDrawStyle(DlDrawStyle::kStroke);
757 builder.DrawRect(SkRect::MakeLTRB(0, 0, 300, 300), rect_paint);
758 builder.DrawCircle(SkPoint::Make(200, 200), 100, paint);
759 // Should render a second circle, centered on the bottom-right-most edge of
760 // the circle.
761 SkMatrix matrix = SkMatrix::Translate((100 + 100 * k1OverSqrt2),
762 (100 + 100 * k1OverSqrt2)) *
763 SkMatrix::Scale(0.5, 0.5) *
764 SkMatrix::Translate(-100, -100);
765 auto backdrop_filter =
766 DlMatrixImageFilter::Make(matrix, DlImageSampling::kLinear);
767 builder.SaveLayer(nullptr, nullptr, backdrop_filter.get());
768 builder.Restore();
769 }
770 builder.Restore();
771
772 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
773 }

References impeller::k1OverSqrt2.

## ◆ TEST_P() [213/454]

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

Definition at line 993 of file aiks_dl_basic_unittests.cc.

994 {
995 DisplayListBuilder builder;
996 builder.Scale(GetContentScale().x, GetContentScale().y);
997 builder.Translate(100, 100);
998 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
999 // +300 translation applied by a SaveLayer image filter.
1000
1001 DlPaint paint;
1002 paint.setImageFilter(DlMatrixImageFilter::Make(
1003 SkMatrix::Translate(300, 0) * SkMatrix::Scale(2, 2),
1004 DlImageSampling::kNearestNeighbor));
1005 builder.SaveLayer(nullptr, &paint);
1006
1007 DlPaint circle_paint;
1008 circle_paint.setColor(DlColor::kGreen());
1009 builder.DrawCircle({-150, 0}, 50, circle_paint);
1010 builder.Restore();
1011
1012 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1013 }

## ◆ TEST_P() [214/454]

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

Definition at line 972 of file aiks_dl_basic_unittests.cc.

972 {
973 DisplayListBuilder builder;
974 builder.Scale(GetContentScale().x, GetContentScale().y);
975 builder.Translate(100, 100);
976 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
977 // +300 translation applied by a SaveLayer image filter.
978 DlPaint paint;
979 SkMatrix translate = SkMatrix::Translate(300, 0);
980 paint.setImageFilter(
981 DlMatrixImageFilter::Make(translate, DlImageSampling::kLinear));
982 builder.SaveLayer(nullptr, &paint);
983
984 DlPaint circle_paint;
985 circle_paint.setColor(DlColor::kGreen());
986 builder.DrawCircle({-300, 0}, 100, circle_paint);
987 builder.Restore();
988
989 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
990 }

## ◆ TEST_P() [215/454]

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

Definition at line 620 of file aiks_dl_unittests.cc.

620 {
621 Scalar scale = 2.0;
622 auto callback = [&]() -> sk_sp<DisplayList> {
623 if (AiksTest::ImGuiBegin("Controls", nullptr,
624 ImGuiWindowFlags_AlwaysAutoResize)) {
625 ImGui::SliderFloat("Scale", &scale, 1, 2);
626 ImGui::End();
627 }
628 DisplayListBuilder builder;
629 builder.Scale(GetContentScale().x, GetContentScale().y);
630 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
631
632 builder.Translate(600, -200);
633
634 SkMatrix matrix = SkMatrix::Scale(scale, scale);
635 DlPaint paint;
636 paint.setImageFilter(
637 DlMatrixImageFilter::Make(matrix, DlImageSampling::kLinear));
638 builder.SaveLayer(nullptr, &paint);
639
640 DlPaint rect_paint;
641 rect_paint.setAlpha(0.5 * 255);
642 builder.DrawImage(image, {0, 0}, DlImageSampling::kLinear, &rect_paint);
643 builder.Restore();
644
645 return builder.Build();
646 };
647
648 ASSERT_TRUE(OpenPlaygroundHere(callback));
649 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and scale.

## ◆ TEST_P() [216/454]

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

Definition at line 775 of file aiks_dl_unittests.cc.

775 {
776 DisplayListBuilder builder;
777
778 DlPaint paint;
779 paint.setColor(DlColor::kBlack());
780 builder.DrawPaint(paint);
781 builder.SaveLayer(nullptr, nullptr);
782 {
783 paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
784 paint.setBlendMode(DlBlendMode::kPlus);
785 builder.DrawCircle({200, 200}, 100, paint);
786 // Should render a second circle, centered on the bottom-right-most edge of
787 // the circle.
788
789 SkMatrix matrix = SkMatrix::Translate((200 + 100 * k1OverSqrt2),
790 (200 + 100 * k1OverSqrt2)) *
791 SkMatrix::Scale(0.5, 0.5) *
792 SkMatrix::Translate(-200, -200);
793 DlPaint save_paint;
794 save_paint.setImageFilter(
795 DlMatrixImageFilter::Make(matrix, DlImageSampling::kLinear));
796
797 builder.SaveLayer(nullptr, &save_paint);
798
799 DlPaint circle_paint;
800 circle_paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
801 circle_paint.setBlendMode(DlBlendMode::kPlus);
802 builder.DrawCircle({200, 200}, 100, circle_paint);
803 builder.Restore();
804 }
805 builder.Restore();
806
807 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
808 }

References impeller::k1OverSqrt2.

## ◆ TEST_P() [217/454]

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

Definition at line 472 of file aiks_dl_unittests.cc.

472 {
473 TextureDescriptor texture_descriptor;
474 texture_descriptor.size = ISize{1024, 1024};
475 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
476 texture_descriptor.storage_mode = StorageMode::kHostVisible;
477 texture_descriptor.mip_count = texture_descriptor.size.MipCount();
478
479 std::vector<uint8_t> bytes(4194304);
480 bool alternate = false;
481 for (auto i = 0u; i < 4194304; i += 4) {
482 if (alternate) {
483 bytes[i] = 255;
484 bytes[i + 1] = 0;
485 bytes[i + 2] = 0;
486 bytes[i + 3] = 255;
487 } else {
488 bytes[i] = 0;
489 bytes[i + 1] = 255;
490 bytes[i + 2] = 0;
491 bytes[i + 3] = 255;
492 }
493 alternate = !alternate;
494 }
495
496 ASSERT_EQ(texture_descriptor.GetByteSizeOfBaseMipLevel(), bytes.size());
497 auto mapping = std::make_shared<fml::NonOwnedMapping>(
498 bytes.data(), // data
499 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
500 );
501 auto texture =
502 GetContext()->GetResourceAllocator()->CreateTexture(texture_descriptor);
503
504 auto device_buffer =
505 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
506 auto command_buffer = GetContext()->CreateCommandBuffer();
507 auto blit_pass = command_buffer->CreateBlitPass();
508
509 blit_pass->AddCopy(DeviceBuffer::AsBufferView(std::move(device_buffer)),
510 texture);
511 blit_pass->GenerateMipmap(texture);
512 EXPECT_TRUE(blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()));
513 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({command_buffer}).ok());
514
515 auto image = DlImageImpeller::Make(texture);
516
517 DisplayListBuilder builder;
518 builder.DrawImageRect(
519 image,
520 SkRect::MakeSize(
521 SkSize::Make(texture->GetSize().width, texture->GetSize().height)),
522 SkRect::MakeLTRB(0, 0, 100, 100), DlImageSampling::kMipmapLinear);
523
524 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
525 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::DlImageImpeller::Make(), impeller::TextureDescriptor::mip_count, impeller::TSize< T >::MipCount(), impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [218/454]

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

Definition at line 173 of file aiks_dl_blend_unittests.cc.

173 {
174 DlPaint paint;
175 DisplayListBuilder builder;
176 // Default is kSourceOver.
177
178 paint.setColor(DlColor::RGBA(1, 0, 0, 0.5));
179 builder.DrawCircle({150, 200}, 100, paint);
180
181 paint.setColor(DlColor::RGBA(0, 1, 0, 0.5));
182 builder.DrawCircle({250, 200}, 100, paint);
183
184 paint.setBlendMode(DlBlendMode::kPlus);
185
186 paint.setColor(DlColor::kRed());
187 builder.DrawCircle({450, 250}, 100, paint);
188
189 paint.setColor(DlColor::kGreen());
190 builder.DrawCircle({550, 250}, 100, paint);
191
192 paint.setColor(DlColor::kBlue());
193 builder.DrawCircle({500, 150}, 100, paint);
194
195 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
196 }

## ◆ TEST_P() [219/454]

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

Definition at line 1489 of file aiks_dl_basic_unittests.cc.

1489 {
1490 DisplayListBuilder builder;
1491
1492 // Should render a green square in the middle of a blue circle.
1493 DlPaint paint;
1494 builder.SaveLayer(nullptr, &paint);
1495 {
1496 builder.Translate(100, 100);
1497 paint.setColor(DlColor::kBlue());
1498 builder.DrawCircle(SkPoint::Make(200, 200), 200, paint);
1499 builder.ClipRect(SkRect::MakeXYWH(100, 100, 200, 200));
1500
1501 paint.setColor(DlColor::kGreen());
1502 paint.setBlendMode(DlBlendMode::kSrcOver);
1503 paint.setImageFilter(DlColorFilterImageFilter::Make(
1504 DlBlendColorFilter::Make(DlColor::kWhite(), DlBlendMode::kDst)));
1505 builder.DrawCircle(SkPoint::Make(200, 200), 200, paint);
1506 builder.Restore();
1507 }
1508
1509 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1510 }

## ◆ TEST_P() [220/454]

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

Definition at line 585 of file aiks_dl_unittests.cc.

585 {
586 auto context = MakeContext();
587 std::weak_ptr<Texture> weak_texture;
588
589 {
590 auto texture = CreateTextureForFixture("table_mountain_nx.png");
591 weak_texture = texture;
592
593 DisplayListBuilder builder;
594 builder.Scale(GetContentScale().x, GetContentScale().y);
595 builder.Translate(100.0f, 100.0f);
596
597 DlPaint paint;
598 paint.setColorSource(std::make_shared<DlImageColorSource>(
599 DlImageImpeller::Make(texture), DlTileMode::kClamp, DlTileMode::kClamp,
600 DlImageSampling::kLinear, nullptr));
601
602 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
603
604 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
605 }
606
607 // See https://github.com/flutter/flutter/issues/134751.
608 //
609 // If the fence waiter was working this may not be released by the end of the
610 // scope above. Adding a manual shutdown so that future changes to the fence
611 // waiter will not flake this test.
612 context->Shutdown();
613
614 // The texture should be released by now.
615 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
616 "by the backend, it should be "
617 "released.";
618 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [221/454]

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

Definition at line 30 of file aiks_dl_path_unittests.cc.

30 {
31 DisplayListBuilder builder;
32 builder.Transform(SkMatrix::Translate(300, 300) * SkMatrix::RotateDeg(90));
33
34 SkPath arrow_stem;
35 SkPath arrow_head;
36
37 arrow_stem.moveTo({120, 190}).lineTo({120, 50});
38 arrow_head.moveTo({50, 120}).lineTo({120, 190}).lineTo({190, 120});
39
40 auto filter =
41 DlBlendColorFilter::Make(DlColor::kAliceBlue(), DlBlendMode::kSrcIn);
42
43 DlPaint paint;
44 paint.setStrokeWidth(15.0);
45 paint.setStrokeCap(DlStrokeCap::kRound);
46 paint.setStrokeJoin(DlStrokeJoin::kRound);
47 paint.setDrawStyle(DlDrawStyle::kStroke);
48 paint.setColorFilter(filter);
49 paint.setColor(DlColor::kBlack());
50
51 builder.DrawPath(arrow_stem, paint);
52 builder.DrawPath(arrow_head, paint);
53
54 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
55 }

## ◆ TEST_P() [222/454]

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

Definition at line 1345 of file aiks_dl_basic_unittests.cc.

1345 {
1346 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1347 DisplayListBuilder builder;
1348 DlPaint paint;
1349
1350 paint.setColor(DlColor::kBlack());
1351 SkRect rect = SkRect::MakeXYWH(25, 25, 25, 25);
1352 builder.DrawRect(rect, paint);
1353
1354 builder.Translate(10, 10);
1355
1356 DlPaint save_paint;
1357 builder.SaveLayer(nullptr, &save_paint);
1358
1359 paint.setColor(DlColor::kGreen());
1360 builder.DrawRect(rect, paint);
1361
1362 builder.Restore();
1363
1364 builder.Translate(10, 10);
1365 paint.setColor(DlColor::kRed());
1366 builder.DrawRect(rect, paint);
1367
1368 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1369 }

## ◆ TEST_P() [223/454]

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

Definition at line 1437 of file aiks_dl_basic_unittests.cc.

1437 {
1438 DisplayListBuilder builder;
1439
1440 builder.Scale(GetContentScale().x, GetContentScale().y);
1441 builder.Translate(100, 100);
1442
1443 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
1444 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
1445 builder.SaveLayer(nullptr, &paint);
1446 builder.DrawImage(texture, {}, DlImageSampling::kLinear);
1447 builder.Restore();
1448 };
1449
1450 DlPaint effect_paint;
1451 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
1452 draw_image_layer(effect_paint);
1453
1454 builder.Translate(300, 300);
1455 builder.Scale(3, 3);
1456 draw_image_layer(effect_paint);
1457
1458 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1459 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [224/454]

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

Definition at line 551 of file aiks_dl_unittests.cc.

551 {
552 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
553
554 // Replace part of the texture with a red rectangle.
555 std::vector<uint8_t> bytes(100 * 100 * 4);
556 for (auto i = 0u; i < bytes.size(); i += 4) {
557 bytes[i] = 255;
558 bytes[i + 1] = 0;
559 bytes[i + 2] = 0;
560 bytes[i + 3] = 255;
561 }
562 auto mapping =
563 std::make_shared<fml::NonOwnedMapping>(bytes.data(), bytes.size());
564 auto device_buffer =
565 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
566 auto cmd_buffer = GetContext()->CreateCommandBuffer();
567 auto blit_pass = cmd_buffer->CreateBlitPass();
568 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), bridge,
569 IRect::MakeLTRB(50, 50, 150, 150));
570
571 auto did_submit =
572 blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()) &&
573 GetContext()->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok();
574 ASSERT_TRUE(did_submit);
575
576 auto image = DlImageImpeller::Make(bridge);
577
578 DisplayListBuilder builder;
579 builder.DrawImage(image, {0, 0}, {});
580
581 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
582 }

References impeller::DeviceBuffer::AsBufferView(), impeller::DlImageImpeller::Make(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST_P() [225/454]

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

Definition at line 1371 of file aiks_dl_basic_unittests.cc.

1371 {
1372 DisplayListBuilder builder;
1373 DlPaint paint;
1374 SkRect rect = SkRect::MakeXYWH(0, 0, 1000, 1000);
1375
1376 // Black, green, and red squares offset by [10, 10].
1377 {
1378 DlPaint save_paint;
1379 SkRect bounds = SkRect::MakeXYWH(25, 25, 25, 25);
1380 builder.SaveLayer(&bounds, &save_paint);
1381 paint.setColor(DlColor::kBlack());
1382 builder.DrawRect(rect, paint);
1383 builder.Restore();
1384 }
1385
1386 {
1387 DlPaint save_paint;
1388 SkRect bounds = SkRect::MakeXYWH(35, 35, 25, 25);
1389 builder.SaveLayer(&bounds, &save_paint);
1390 paint.setColor(DlColor::kGreen());
1391 builder.DrawRect(rect, paint);
1392 builder.Restore();
1393 }
1394
1395 {
1396 DlPaint save_paint;
1397 SkRect bounds = SkRect::MakeXYWH(45, 45, 25, 25);
1398 builder.SaveLayer(&bounds, &save_paint);
1399 paint.setColor(DlColor::kRed());
1400 builder.DrawRect(rect, paint);
1401 builder.Restore();
1402 }
1403
1404 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1405 }

## ◆ TEST_P() [226/454]

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

Definition at line 129 of file aiks_dl_blur_unittests.cc.

129 {
130 DisplayListBuilder builder;
131 builder.Scale(GetContentScale().x, GetContentScale().y);
132
133 std::vector<float> sigmas = {0.0, 0.01, 1.0};
134 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
135 DlColor::kRed()};
136 for (uint32_t i = 0; i < sigmas.size(); ++i) {
137 DlPaint paint;
138 paint.setColor(colors[i]);
139 paint.setMaskFilter(
140 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
141
142 builder.Save();
143 builder.Translate(100 + (i * 100), 100);
144 SkRRect rrect =
145 SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 100.0f, 100.0f), 100, 100);
146 builder.DrawRRect(rrect, paint);
147 builder.Restore();
148 }
149
150 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
151 }

## ◆ TEST_P() [227/454]

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

Definition at line 723 of file aiks_dl_basic_unittests.cc.

723 {
724 DisplayListBuilder builder;
725 builder.Scale(GetContentScale().x, GetContentScale().y);
726 DlPaint paint;
727 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
728
729 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
730
731 paint.setColor(
732 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
733 Scalar y = 100.0f;
734 for (int i = 0; i < 5; i++) {
735 Scalar x = (i + 1) * 100;
736 Scalar radius = x / 10.0f;
737 builder.DrawRect(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
738 radius, 60.0f - radius),
739 paint);
740 }
741
742 paint.setColor(DlColor::kBlue());
743 y += 100.0f;
744 for (int i = 0; i < 5; i++) {
745 Scalar x = (i + 1) * 100;
746 Scalar radius = x / 10.0f;
747 builder.DrawCircle({x + 25, y + 25}, radius, paint);
748 }
749
750 paint.setColor(DlColor::kGreen());
751 y += 100.0f;
752 for (int i = 0; i < 5; i++) {
753 Scalar x = (i + 1) * 100;
754 Scalar radius = x / 10.0f;
755 builder.DrawOval(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
756 radius, 60.0f - radius),
757 paint);
758 }
759
760 paint.setColor(
761 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
762 y += 100.0f;
763 for (int i = 0; i < 5; i++) {
764 Scalar x = (i + 1) * 100;
765 Scalar radius = x / 20.0f;
766 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f),
767 radius, radius),
768 paint);
769 }
770
771 paint.setColor(
772 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
773 y += 100.0f;
774 for (int i = 0; i < 5; i++) {
775 Scalar x = (i + 1) * 100;
776 Scalar radius = x / 20.0f;
777 builder.DrawRRect(
778 SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, 5.0f),
779 paint);
780 }
781
782 auto dl = builder.Build();
783 ASSERT_TRUE(OpenPlaygroundHere(dl));
784 }

## ◆ TEST_P() [228/454]

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

Definition at line 39 of file aiks_dl_blur_unittests.cc.

39 {
40 DisplayListBuilder builder;
41 builder.Scale(GetContentScale().x, GetContentScale().y);
42
43 std::vector<float> sigmas = {0.0, 0.01, 1.0};
44 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
45 DlColor::kRed()};
46 for (uint32_t i = 0; i < sigmas.size(); ++i) {
47 DlPaint paint;
48 paint.setColor(colors[i]);
49 paint.setMaskFilter(
50 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
51
52 builder.Save();
53 builder.Translate(100 + (i * 100), 100);
54 SkRRect rrect =
55 SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 60.0f, 160.0f), 50, 100);
56 builder.DrawRRect(rrect, paint);
57 builder.Restore();
58 }
59
60 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
61 }

## ◆ TEST_P() [229/454]

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

Definition at line 227 of file aiks_dl_path_unittests.cc.

227 {
228 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
229 auto callback = [&]() -> sk_sp<DisplayList> {
230 static Color color = Color::Black().WithAlpha(0.5);
231 static float scale = 3;
232 static bool add_circle_clip = true;
233
234 if (AiksTest::ImGuiBegin("Controls", nullptr,
235 ImGuiWindowFlags_AlwaysAutoResize)) {
236 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
237 ImGui::SliderFloat("Scale", &scale, 0, 6);
238 ImGui::Checkbox("Circle clip", &add_circle_clip);
239 ImGui::End();
240 }
241
242 DisplayListBuilder builder;
243 builder.Scale(GetContentScale().x, GetContentScale().y);
244 DlPaint paint;
245
246 paint.setColor(DlColor::kWhite());
247 builder.DrawPaint(paint);
248
249 paint.setColor(
250 DlColor::ARGB(color.alpha, color.red, color.green, color.blue));
251 paint.setDrawStyle(DlDrawStyle::kStroke);
252 paint.setStrokeWidth(10);
253
254 SkPath path;
255 path.moveTo({20, 20});
256 path.quadTo({60, 20}, {60, 60});
257 path.close();
258 path.moveTo({60, 20});
259 path.quadTo({60, 60}, {20, 60});
260
261 builder.Scale(scale, scale);
262
263 if (add_circle_clip) {
264 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
265 Color::Red());
266 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
267 Color::Red());
268 auto [handle_a, handle_b] =
269 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
270
271 SkMatrix screen_to_canvas = SkMatrix::I();
272 if (!builder.GetTransform().invert(&screen_to_canvas)) {
273 return nullptr;
274 }
275
276 SkPoint point_a =
277 screen_to_canvas.mapPoint(SkPoint::Make(handle_a.x, handle_a.y));
278 SkPoint point_b =
279 screen_to_canvas.mapPoint(SkPoint::Make(handle_b.x, handle_b.y));
280
281 SkPoint middle = point_a + point_b;
282 middle.scale(GetContentScale().x / 2);
283
284 auto radius = SkPoint::Distance(point_a, middle);
285
286 builder.ClipPath(SkPath::Circle(middle.x(), middle.y(), radius));
287 }
288
289 for (auto join :
290 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
291 paint.setStrokeJoin(join);
292 for (auto cap :
293 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
294 paint.setStrokeCap(cap);
295 builder.DrawPath(path, paint);
296 builder.Translate(80, 0);
297 }
298 builder.Translate(-240, 60);
299 }
300
301 return builder.Build();
302 };
303
304 ASSERT_TRUE(OpenPlaygroundHere(callback));
305 }

References impeller::Color::Black(), color, impeller::DrawPlaygroundLine(), impeller::AiksPlayground::ImGuiBegin(), impeller::Color::Red(), scale, and impeller::Color::WithAlpha().

## ◆ TEST_P() [230/454]

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

Definition at line 119 of file aiks_dl_unittests.cc.

119 {
120 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
121
122 DlPaint paint;
123 paint.setColorFilter(DlLinearToSrgbGammaColorFilter::kInstance);
124 builder.SaveLayer(nullptr, &paint);
125
126 builder.Translate(500, 300);
127 builder.Rotate(120); // 120 deg
128
129 DlPaint draw_paint;
130 draw_paint.setColor(DlColor::kBlue());
131 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
132
133 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
134 }

## ◆ TEST_P() [231/454]

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

Definition at line 477 of file aiks_dl_basic_unittests.cc.

477 {
478 DisplayListBuilder builder;
479 builder.Scale(GetContentScale().x, GetContentScale().y);
480 DlPaint paint;
481 const int color_count = 3;
482 DlColor colors[color_count] = {
483 DlColor::kBlue(),
484 DlColor::kGreen(),
485 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
486 };
487
488 paint.setColor(DlColor::kWhite());
489 builder.DrawPaint(paint);
490
491 int c_index = 0;
492
493 auto draw = [&paint, &colors, &c_index](DlCanvas& canvas, SkPoint center,
494 Scalar r, Scalar dr, int n) {
495 for (int i = 0; i < n; i++) {
496 paint.setColor(colors[(c_index++) % color_count]);
497 canvas.DrawCircle(center, r, paint);
498 r += dr;
499 }
500 };
501
502 paint.setDrawStyle(DlDrawStyle::kStroke);
503 paint.setStrokeWidth(1);
504 draw(builder, {10, 10}, 2, 2, 14); // r = [2, 28], covers [1,29]
505 paint.setStrokeWidth(5);
506 draw(builder, {10, 10}, 35, 10, 56); // r = [35, 585], covers [30,590]
507
508 DlColor gradient_colors[7] = {
509 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
510 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
511 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
512 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
513 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
514 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
515 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
516 };
517 DlScalar stops[7] = {
518 0.0,
519 (1.0 / 6.0) * 1,
520 (1.0 / 6.0) * 2,
521 (1.0 / 6.0) * 3,
522 (1.0 / 6.0) * 4,
523 (1.0 / 6.0) * 5,
524 1.0,
525 };
526 auto texture = CreateTextureForFixture("airplane.jpg",
527 /*enable_mipmapping=*/true);
528 auto image = DlImageImpeller::Make(texture);
529
530 paint.setColorSource(DlColorSource::MakeRadial(
531 {500, 600}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
532 draw(builder, {500, 600}, 5, 10, 10);
533
534 SkMatrix local_matrix = SkMatrix::Translate(700, 200);
535 DlImageColorSource image_source(
536 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
537 DlImageSampling::kNearestNeighbor, &local_matrix);
538 paint.setColorSource(&image_source);
539 draw(builder, {800, 300}, 5, 10, 10);
540
541 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
542 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [232/454]

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

Definition at line 528 of file aiks_dl_unittests.cc.

528 {
529 SkPath path;
530 path.moveTo(0, 400)
531 .lineTo(0, 0)
532 .lineTo(400, 0)
533 // MoveTo implicitly adds a contour, ensure that close doesn't
534 // add another nearly-empty contour.
535 .moveTo(0, 400)
536 .close();
537
538 DisplayListBuilder builder;
539 builder.Translate(50, 50);
540
541 DlPaint paint;
542 paint.setColor(DlColor::kBlue());
543 paint.setStrokeCap(DlStrokeCap::kRound);
544 paint.setStrokeWidth(10);
545 paint.setDrawStyle(DlDrawStyle::kStroke);
546 builder.DrawPath(path, paint);
547
548 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
549 }

## ◆ TEST_P() [233/454]

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

Definition at line 943 of file aiks_dl_basic_unittests.cc.

943 {
944 DisplayListBuilder builder;
945
946 // Use a non-srcOver blend mode to ensure that we don't detect this as an
947 // opacity peephole optimization.
948 DlPaint paint;
949 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
950 paint.setBlendMode(DlBlendMode::kSrc);
951
952 SkRect bounds = SkRect::MakeLTRB(0, 0, 200, 200);
953 builder.SaveLayer(&bounds, &paint);
954
955 paint.setColor(DlColor::kTransparent());
956 paint.setBlendMode(DlBlendMode::kSrc);
957 builder.DrawPaint(paint);
958 builder.Restore();
959
960 paint.setColor(DlColor::kBlue());
961 paint.setBlendMode(DlBlendMode::kDstOver);
962 builder.SaveLayer(nullptr, &paint);
963 builder.Restore();
964
965 // This playground should appear blank on CI since we are only drawing
966 // transparent black. If the clear color optimization is broken, the texture
967 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
968 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
969 }

## ◆ TEST_P() [234/454]

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

Definition at line 500 of file aiks_dl_text_unittests.cc.

500 {
501 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
502 ASSERT_NE(mapping, nullptr);
503
504 Scalar font_size = 100;
505 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
506 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
507
508 DlPaint text_paint;
509 text_paint.setColor(DlColor::kBlue());
510
511 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
512 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
513 std::vector<Scalar> stops = {
514 0.0,
515 1.0,
516 };
517 text_paint.setColorSource(DlColorSource::MakeLinear(
518 /*start_point=*/{0, 0}, //
519 /*end_point=*/{100, 100}, //
520 /*stop_count=*/2, //
521 /*colors=*/colors.data(), //
522 /*stops=*/stops.data(), //
523 /*tile_mode=*/DlTileMode::kRepeat //
524 ));
525
526 DisplayListBuilder builder;
527 builder.Translate(100, 100);
528 builder.Rotate(45);
529
530 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
531 ASSERT_NE(blob, nullptr);
532 auto frame = MakeTextFrameFromTextBlobSkia(blob);
533 builder.DrawTextFrame(frame, 0, 0, text_paint);
534
535 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
536 }

References font_size, and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [235/454]

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

Definition at line 222 of file aiks_dl_text_unittests.cc.

222 {
223 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
224 std::array<Scalar, 20> phase_offsets = {
225 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
226 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
227 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
228 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
229 auto callback = [&]() -> sk_sp<DisplayList> {
230 static float font_size = 20;
231 static float phase_variation = 0.2;
232 static float speed = 0.5;
233 static float magnitude = 100;
234 if (AiksTest::ImGuiBegin("Controls", nullptr,
235 ImGuiWindowFlags_AlwaysAutoResize)) {
236 ImGui::SliderFloat("Font size", &font_size, 5, 50);
237 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
238 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
239 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
240 ImGui::End();
241 }
242
243 DisplayListBuilder builder;
244 builder.Scale(GetContentScale().x, GetContentScale().y);
245
246 for (size_t i = 0; i < phase_offsets.size(); i++) {
247 SkPoint position = SkPoint::Make(
248 200 +
249 magnitude * std::sin((-phase_offsets[i] * k2Pi * phase_variation +
250 GetSecondsElapsed() * speed)), //
251 200 + i * font_size * 1.1 //
252 );
253 if (!RenderTextInCanvasSkia(
254 GetContext(), builder,
255 "the quick brown fox jumped over "
256 "the lazy dog!.?",
257 "Roboto-Regular.ttf",
258 {.font_size = font_size, .position = position})) {
259 return nullptr;
260 }
261 }
262 return builder.Build();
263 };
264
265 ASSERT_TRUE(OpenPlaygroundHere(callback));
266 }

References font_size, impeller::k2Pi, and RenderTextInCanvasSkia().

## ◆ TEST_P() [236/454]

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

Definition at line 394 of file aiks_dl_text_unittests.cc.

394 {
395 DisplayListBuilder builder;
396
397 builder.Scale(GetContentScale().x, GetContentScale().y);
398 DlPaint paint;
399 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
400 builder.DrawPaint(paint);
401
402 builder.Transform(SkM44::ColMajor(Matrix(0.25, -0.3, 0, -0.002, //
403 0, 0.5, 0, 0, //
404 0, 0, 0.3, 0, //
405 100, 100, 0, 1.3)
406 .m));
407 ASSERT_TRUE(RenderTextInCanvasSkia(
408 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
409 "Roboto-Regular.ttf"));
410
411 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
412 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [237/454]

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

Definition at line 26 of file canvas_unittests.cc.

26 {
27 ContentContext context(GetContext(), nullptr);
28 auto canvas = CreateTestCanvas(context);
29
30 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix());
31
32 // clang-format off
33 canvas->Translate(Vector3(100, 200));
34 ASSERT_MATRIX_NEAR(
35 canvas->GetCurrentTransform(),
36 Matrix( 1, 0, 0, 0,
37 0, 1, 0, 0,
38 0, 0, 1, 0,
39 100, 200, 0, 1));
40
41 canvas->Rotate(Radians(kPiOver2));
42 ASSERT_MATRIX_NEAR(
43 canvas->GetCurrentTransform(),
44 Matrix( 0, 1, 0, 0,
45 -1, 0, 0, 0,
46 0, 0, 1, 0,
47 100, 200, 0, 1));
48
49 canvas->Scale(Vector3(2, 3));
50 ASSERT_MATRIX_NEAR(
51 canvas->GetCurrentTransform(),
52 Matrix( 0, 2, 0, 0,
53 -3, 0, 0, 0,
54 0, 0, 0, 0,
55 100, 200, 0, 1));
56
57 canvas->Translate(Vector3(100, 200));
58 ASSERT_MATRIX_NEAR(
59 canvas->GetCurrentTransform(),
60 Matrix( 0, 2, 0, 0,
61 -3, 0, 0, 0,
62 0, 0, 0, 0,
63 -500, 400, 0, 1));
64 // clang-format on
65 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::kPiOver2.

## ◆ TEST_P() [238/454]

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

Definition at line 136 of file aiks_dl_unittests.cc.

136 {
137 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
138
139 DlPaint paint;
140 paint.setColor(DlColor::kBlue());
141 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
142
143 DlPaint save_paint;
144 save_paint.setColor(DlColor::kBlack().withAlpha(128));
145 builder.SaveLayer(nullptr, &save_paint);
146 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), paint);
147 builder.Restore();
148
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }

## ◆ TEST_P() [239/454]

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

Definition at line 241 of file aiks_dl_unittests.cc.

241 {
242 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
243
244 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
245 builder.DrawImage(image, {100, 100}, DlImageSampling::kMipmapLinear);
246
247 DlPaint paint;
248 paint.setColor(DlColor::kBlack().withAlpha(128));
249 builder.SaveLayer(nullptr, &paint);
250 builder.DrawImage(image, {100, 500}, DlImageSampling::kMipmapLinear);
251 builder.Restore();
252
253 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
254 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [240/454]

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

Definition at line 326 of file aiks_dl_unittests.cc.

326 {
327 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
328
329 DlPaint paint;
330 paint.setColor(DlColor::kRed());
331 builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), paint);
332
333 DlPaint save_paint;
334 save_paint.setAlpha(128);
335 save_paint.setBlendMode(DlBlendMode::kLighten);
336 builder.SaveLayer(nullptr, &save_paint);
337
338 DlPaint draw_paint;
339 draw_paint.setColor(DlColor::kGreen());
340 builder.DrawCircle({200, 200}, 100, draw_paint);
341 builder.Restore();
342
343 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
344 }

## ◆ TEST_P() [241/454]

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

Definition at line 152 of file aiks_dl_unittests.cc.

152 {
153 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
154
155 DlPaint paint;
156 paint.setColor(DlColor::kBlue());
157 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
158
159 DlPaint save_paint;
160 paint.setColor(DlColor::kBlack().withAlpha(128));
161 paint.setColorFilter(
162 DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kDstOver));
163 builder.SaveLayer(nullptr, &paint);
164
165 DlPaint draw_paint;
166 draw_paint.setColor(DlColor::kBlue());
167 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
168 builder.Restore();
169
170 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
171 }

## ◆ TEST_P() [242/454]

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

Definition at line 173 of file aiks_dl_unittests.cc.

173 {
174 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
175
176 DlPaint paint;
177 paint.setColor(DlColor::kBlue());
178 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
179
180 DlPaint save_paint;
181 save_paint.setColor(DlColor::kBlack().withAlpha(128));
182 save_paint.setImageFilter(DlColorFilterImageFilter::Make(
183 DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kDstOver)));
184
185 builder.SaveLayer(nullptr, &save_paint);
186
187 DlPaint draw_paint;
188 draw_paint.setColor(DlColor::kBlue());
189 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
190 builder.Restore();
191
192 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
193 }

## ◆ TEST_P() [243/454]

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

Definition at line 195 of file aiks_dl_unittests.cc.

195 {
196 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
197
198 DlPaint paint;
199 paint.setColor(DlColor::kBlue());
200 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
201
202 DlPaint save_paint;
203 save_paint.setColor(DlColor::kBlack().withAlpha(128));
204 save_paint.setColorFilter(
205 DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kDstOver));
206 builder.SaveLayer(nullptr, &save_paint);
207
208 DlPaint draw_paint;
209 draw_paint.setColor(DlColor::kBlue());
210 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
211 builder.Restore();
212
213 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
214 }

## ◆ TEST_P() [244/454]

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

Definition at line 300 of file aiks_dl_unittests.cc.

301 {
302 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
303
304 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
305 builder.DrawImage(image, {100, 100}, {});
306
307 const float matrix[20] = {
308 1, 0, 0, 0, 0, //
309 0, 1, 0, 0, 0, //
310 0, 0.2, 1, 0, 0, //
311 0, 0, 0, 0.5, 0 //
312 };
313 DlPaint paint;
314 paint.setColor(DlColor::kBlack().withAlpha(128));
315 paint.setImageFilter(
316 DlColorFilterImageFilter::Make(DlMatrixColorFilter::Make(matrix)));
317 paint.setColorFilter(
318 DlBlendColorFilter::Make(DlColor::kGreen(), DlBlendMode::kModulate));
319 builder.SaveLayer(nullptr, &paint);
320 builder.DrawImage(image, {100, 500}, {});
321 builder.Restore();
322
323 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
324 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [245/454]

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

Definition at line 256 of file aiks_dl_unittests.cc.

256 {
257 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
258
259 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
260 builder.DrawImage(image, {100, 100}, {});
261
262 const float matrix[20] = {
263 1, 0, 0, 0, 0, //
264 0, 1, 0, 0, 0, //
265 0, 0, 1, 0, 0, //
266 0, 0, 0, 2, 0 //
267 };
268 DlPaint paint;
269 paint.setColor(DlColor::kBlack().withAlpha(128));
270 paint.setColorFilter(DlMatrixColorFilter::Make(matrix));
271 builder.SaveLayer(nullptr, &paint);
272 builder.DrawImage(image, {100, 500}, {});
273 builder.Restore();
274
275 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
276 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [246/454]

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

Definition at line 278 of file aiks_dl_unittests.cc.

278 {
279 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
280
281 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
282 builder.DrawImage(image, {100, 100}, {});
283
284 const float matrix[20] = {
285 1, 0, 0, 0, 0, //
286 0, 1, 0, 0, 0, //
287 0, 0, 1, 0, 0, //
288 0, 0, 0, 2, 0 //
289 };
290 DlPaint paint;
291 paint.setColor(DlColor::kBlack().withAlpha(128));
292 paint.setColorFilter(DlMatrixColorFilter::Make(matrix));
293 builder.SaveLayer(nullptr, &paint);
294 builder.DrawImage(image, {100, 500}, {});
295 builder.Restore();
296
297 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
298 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [247/454]

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

Definition at line 851 of file aiks_dl_unittests.cc.

851 {
852 DisplayListBuilder builder;
853 builder.Save();
854 builder.Scale(1.618, 1.618);
855 SkPath path = SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100));
856
857 builder.DrawShadow(path, flutter::DlColor::kTransparent(), 15, false, 1);
858 builder.Restore();
859
860 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
861 }

## ◆ TEST_P() [248/454]

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 }

## ◆ TEST_P() [249/454]

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

Definition at line 94 of file aiks_dl_vertices_unittests.cc.

94 {
95 DisplayListBuilder builder;
96 DlPaint paint;
97 auto image =
98 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
99 auto size = image->impeller_texture()->GetSize();
100
101 paint.setColorSource(std::make_shared<DlImageColorSource>(
102 image, DlTileMode::kClamp, DlTileMode::kClamp));
103
104 std::vector<SkPoint> positions = {
105 SkPoint::Make(0, 0), SkPoint::Make(size.width, 0),
106 SkPoint::Make(0, size.height), SkPoint::Make(size.width, 0),
107 SkPoint::Make(0, 0), SkPoint::Make(size.width, size.height),
108 };
109 std::vector<DlColor> colors = {
110 DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
111 DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
112 DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
113 };
114
115 auto vertices =
116 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
117
118 builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
119 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
120 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [250/454]

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

Definition at line 122 of file aiks_dl_vertices_unittests.cc.

122 {
123 DisplayListBuilder builder;
124 DlPaint paint;
125 auto image =
126 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
127 auto size = image->impeller_texture()->GetSize();
128
129 paint.setColorSource(std::make_shared<DlImageColorSource>(
130 image, DlTileMode::kClamp, DlTileMode::kClamp));
131
132 std::vector<SkPoint> positions = {
133 SkPoint::Make(0, 0), SkPoint::Make(size.width, 0),
134 SkPoint::Make(0, size.height), SkPoint::Make(size.width, 0),
135 SkPoint::Make(0, 0), SkPoint::Make(size.width, size.height),
136 };
137 std::vector<DlColor> colors = {
138 DlColor::kRed().modulateOpacity(0.5),
139 DlColor::kBlue().modulateOpacity(0.5),
140 DlColor::kGreen().modulateOpacity(0.5),
141 DlColor::kRed().modulateOpacity(0.5),
142 DlColor::kBlue().modulateOpacity(0.5),
143 DlColor::kGreen().modulateOpacity(0.5),
144 };
145
146 auto vertices =
147 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
148
149 builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
150 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
151 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [251/454]

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

Definition at line 48 of file aiks_dl_vertices_unittests.cc.

48 {
49 DisplayListBuilder builder;
50 DlPaint paint;
51 auto image =
52 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
53 auto size = image->impeller_texture()->GetSize();
54
55 paint.setColorSource(std::make_shared<DlImageColorSource>(
56 image, DlTileMode::kClamp, DlTileMode::kClamp));
57
58 std::vector<SkPoint> vertex_coordinates = {SkPoint::Make(0, 0),
59 SkPoint::Make(size.width, 0),
60 SkPoint::Make(0, size.height)};
61 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
62 {0, 1, 2}, {}, {});
63
64 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
65 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
66 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [252/454]

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

Definition at line 69 of file aiks_dl_vertices_unittests.cc.

69 {
70 DisplayListBuilder builder;
71 DlPaint paint;
72 auto image =
73 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
74 auto size = image->impeller_texture()->GetSize();
75
76 SkMatrix matrix;
77 matrix.setTranslateX(100);
78 matrix.setTranslateY(100);
79 paint.setColorSource(std::make_shared<DlImageColorSource>(
80 image, DlTileMode::kClamp, DlTileMode::kClamp, DlImageSampling::kLinear,
81 &matrix));
82
83 std::vector<SkPoint> positions = {SkPoint::Make(0, 0),
84 SkPoint::Make(size.width, 0),
85 SkPoint::Make(0, size.height)};
86 auto vertices =
87 MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
88
89 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
90 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
91 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [253/454]

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().ConvertTo<MebiBytes>().GetSize(),
33 0u);
34
35 // Memoryless texture does not increase allocated size.
36 {
37 TextureDescriptor desc;
38 desc.format = PixelFormat::kR8G8B8A8UNormInt;
39 desc.storage_mode = StorageMode::kDeviceTransient;
40 desc.size = {1024, 1024};
41 auto texture_1 = allocator->CreateTexture(desc);
42
43 // Private storage texture increases allocated size.
44 desc.storage_mode = StorageMode::kDevicePrivate;
45 auto texture_2 = allocator->CreateTexture(desc);
46
47 #ifdef IMPELLER_DEBUG
48 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
49 4u);
50 #else
51 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
52 0u);
53 #endif // IMPELLER_DEBUG
54
55 // Host storage texture increases allocated size.
56 desc.storage_mode = StorageMode::kHostVisible;
57 auto texture_3 = allocator->CreateTexture(desc);
58
59 #ifdef IMPELLER_DEBUG
60 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
61 8u);
62 #else
63 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
64 0u);
65 #endif // IMPELLER_DEBUG
66 }
67
68 // After all textures are out of scope, memory has been decremented.
69 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
70 0u);
71 }

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::TextureDescriptor::format, impeller::AllocationSize< Period >::GetSize(), impeller::kDevicePrivate, impeller::kDeviceTransient, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [254/454]

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() [255/454]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentPixelFormatsFails |
| ) |  |

Definition at line 22 of file blit_pass_unittests.cc.

22 {
23 ScopedValidationDisable scope; // avoid noise in output.
24 auto context = GetContext();
25 auto cmd_buffer = context->CreateCommandBuffer();
26 auto blit_pass = cmd_buffer->CreateBlitPass();
27
28 TextureDescriptor src_desc;
29 src_desc.format = PixelFormat::kA8UNormInt;
30 src_desc.size = {100, 100};
31 src_desc.storage_mode = StorageMode::kHostVisible;
32 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
33
34 TextureDescriptor dst_format;
35 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
36 dst_format.size = {100, 100};
37 dst_format.storage_mode = StorageMode::kHostVisible;
38 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
39
40 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
41 }

References impeller::TextureDescriptor::format, impeller::kA8UNormInt, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [256/454]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentSampleCountsFails |
| ) |  |

Definition at line 43 of file blit_pass_unittests.cc.

43 {
44 ScopedValidationDisable scope; // avoid noise in output.
45 auto context = GetContext();
46 auto cmd_buffer = context->CreateCommandBuffer();
47 auto blit_pass = cmd_buffer->CreateBlitPass();
48
49 TextureDescriptor src_desc;
50 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
51 src_desc.sample_count = SampleCount::kCount4;
52 src_desc.size = {100, 100};
53 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
54
55 TextureDescriptor dst_format;
56 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
57 dst_format.size = {100, 100};
58 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
59
60 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
61 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::sample_count, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [257/454]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitPassesForMatchingFormats |
| ) |  |

Definition at line 63 of file blit_pass_unittests.cc.

63 {
64 ScopedValidationDisable scope; // avoid noise in output.
65 auto context = GetContext();
66 auto cmd_buffer = context->CreateCommandBuffer();
67 auto blit_pass = cmd_buffer->CreateBlitPass();
68
69 TextureDescriptor src_desc;
70 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
71 src_desc.size = {100, 100};
72 src_desc.storage_mode = StorageMode::kHostVisible;
73 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
74
75 TextureDescriptor dst_format;
76 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
77 dst_format.size = {100, 100};
78 dst_format.storage_mode = StorageMode::kHostVisible;
79 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
80
81 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
82 }

References impeller::TextureDescriptor::format, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [258/454]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanBlitSmallRegionToUninitializedTexture |
| ) |  |

Definition at line 112 of file blit_pass_unittests.cc.

112 {
113 auto context = GetContext();
114 auto cmd_buffer = context->CreateCommandBuffer();
115 auto blit_pass = cmd_buffer->CreateBlitPass();
116
117 TextureDescriptor dst_format;
118 dst_format.storage_mode = StorageMode::kDevicePrivate;
119 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
120 dst_format.size = {1000, 1000};
121 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
122
123 DeviceBufferDescriptor src_format;
124 src_format.size = 4;
125 src_format.storage_mode = StorageMode::kHostVisible;
126 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
127
128 ASSERT_TRUE(dst);
129
130 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
131 IRect::MakeLTRB(0, 0, 1, 1), "", /*slice=*/0));
132 EXPECT_TRUE(blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()));
133 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
134 }

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() [259/454]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanResizeTextures |
| ) |  |

Definition at line 136 of file blit_pass_unittests.cc.

136 {
137 auto context = GetContext();
138 auto cmd_buffer = context->CreateCommandBuffer();
139 auto blit_pass = cmd_buffer->CreateBlitPass();
140
141 TextureDescriptor dst_format;
142 dst_format.storage_mode = StorageMode::kDevicePrivate;
143 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
144 dst_format.size = {10, 10};
145 dst_format.usage = TextureUsage::kShaderRead | TextureUsage::kShaderWrite;
146 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
147
148 TextureDescriptor src_format;
149 src_format.storage_mode = StorageMode::kDevicePrivate;
150 src_format.format = PixelFormat::kR8G8B8A8UNormInt;
151 src_format.size = {100, 100};
152 auto src = context->GetResourceAllocator()->CreateTexture(src_format);
153
154 std::vector<uint8_t> bytes(src_format.GetByteSizeOfBaseMipLevel());
155 for (auto i = 0u; i < src_format.GetByteSizeOfBaseMipLevel(); i += 4) {
156 // RGBA
157 bytes[i + 0] = 255;
158 bytes[i + 1] = 0;
159 bytes[i + 2] = 0;
160 bytes[i + 3] = 255;
161 }
162 auto mapping = fml::DataMapping(bytes);
163 auto staging = context->GetResourceAllocator()->CreateBufferWithCopy(mapping);
164
165 ASSERT_TRUE(dst);
166 ASSERT_TRUE(src);
167 ASSERT_TRUE(staging);
168
169 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(staging), src));
170 EXPECT_TRUE(blit_pass->ResizeTexture(src, dst));
171 EXPECT_TRUE(blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()));
172 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
173 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), impeller::kDevicePrivate, impeller::kR8G8B8A8UNormInt, impeller::kShaderRead, impeller::kShaderWrite, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [260/454]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | ChecksInvalidSliceParameters |
| ) |  |

Definition at line 84 of file blit_pass_unittests.cc.

84 {
85 ScopedValidationDisable scope; // avoid noise in output.
86 auto context = GetContext();
87 auto cmd_buffer = context->CreateCommandBuffer();
88 auto blit_pass = cmd_buffer->CreateBlitPass();
89
90 TextureDescriptor dst_format;
91 dst_format.storage_mode = StorageMode::kDevicePrivate;
92 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
93 dst_format.size = {100, 100};
94 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
95
96 DeviceBufferDescriptor src_format;
97 src_format.size = 40000;
98 src_format.storage_mode = StorageMode::kHostVisible;
99 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
100
101 ASSERT_TRUE(dst);
102 ASSERT_TRUE(src);
103
104 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
105 std::nullopt, "", /*slice=*/25));
106 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
107 std::nullopt, "", /*slice=*/6));
108 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
109 std::nullopt, "", /*slice=*/0));
110 }

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() [261/454]

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() [262/454]

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 }

References impeller::interop::Create().

## ◆ TEST_P() [263/454]

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() [264/454]

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 }

References impeller::interop::Create().

## ◆ TEST_P() [265/454]

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() [266/454]

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() [267/454]

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::interop::Create(), and impeller::kCount1.

## ◆ TEST_P() [268/454]

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 }

References impeller::interop::Create().

## ◆ TEST_P() [269/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1175 of file dl_unittests.cc.

1175 {
1176 flutter::DisplayListBuilder builder;
1177
1178 {
1179 builder.SaveLayer(nullptr, nullptr);
1180 builder.Translate(100, 100);
1181 flutter::DlPaint paint;
1182 paint.setColor(flutter::DlColor::kRed());
1183 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1184 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1185 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1186 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1187 builder.Restore();
1188 }
1189 {
1190 builder.SaveLayer(nullptr, nullptr);
1191 builder.Translate(300, 100);
1192 flutter::DlPaint paint;
1193 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1194 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1195 paint.setColor(flutter::DlColor::kRed());
1196 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1197 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1198 builder.Restore();
1199 }
1200 {
1201 builder.SaveLayer(nullptr, nullptr);
1202 builder.Translate(100, 300);
1203 flutter::DlPaint paint;
1204 paint.setColor(flutter::DlColor::kRed());
1205 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1206 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1207 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1208 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1209 builder.Restore();
1210 }
1211 {
1212 builder.SaveLayer(nullptr, nullptr);
1213 builder.Translate(300, 300);
1214 flutter::DlPaint paint;
1215 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1216 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1217 paint.setColor(flutter::DlColor::kRed());
1218 paint.setBlendMode(flutter::DlBlendMode::kDst);
1219 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1220 builder.Restore();
1221 }
1222
1223 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1224 }

## ◆ TEST_P() [270/454]

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

## ◆ TEST_P() [271/454]

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 }

## ◆ TEST_P() [272/454]

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(), scale, stroke_width, and impeller::Color::White().

## ◆ TEST_P() [273/454]

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(), impeller::Color::Red(), scale, and impeller::Color::White().

## ◆ TEST_P() [274/454]

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 }

## ◆ TEST_P() [275/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1226 of file dl_unittests.cc.

1226 {
1227 flutter::DisplayListBuilder builder;
1228 const float green_color_matrix[20] = {
1229 0, 0, 0, 0, 0, //
1230 0, 0, 0, 0, 1, //
1231 0, 0, 0, 0, 0, //
1232 0, 0, 0, 1, 0, //
1233 };
1234 const float blue_color_matrix[20] = {
1235 0, 0, 0, 0, 0, //
1236 0, 0, 0, 0, 0, //
1237 0, 0, 0, 0, 1, //
1238 0, 0, 0, 1, 0, //
1239 };
1240 auto green_color_filter =
1241 std::make_shared<flutter::DlMatrixColorFilter>(green_color_matrix);
1242 auto blue_color_filter =
1243 std::make_shared<flutter::DlMatrixColorFilter>(blue_color_matrix);
1244 auto blue_image_filter =
1245 std::make_shared<flutter::DlColorFilterImageFilter>(blue_color_filter);
1246
1247 flutter::DlPaint paint;
1248 paint.setColor(flutter::DlColor::kRed());
1249 paint.setColorFilter(green_color_filter);
1250 paint.setImageFilter(blue_image_filter);
1251 builder.DrawRect(SkRect::MakeLTRB(100, 100, 500, 500), paint);
1252 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1253 }

## ◆ TEST_P() [276/454]

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() [277/454]

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() [278/454]

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() [279/454]

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() [280/454]

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() [281/454]

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() [282/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1123 of file dl_unittests.cc.

1123 {
1124 const flutter::DlColor colors[2] = {
1125 flutter::DlColor(0xFFF44336),
1126 flutter::DlColor(0xFF2196F3),
1127 };
1128 const float stops[2] = {0.0, 1.0};
1129 flutter::DlPaint paint;
1130 flutter::DisplayListBuilder builder;
1131 auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
1132 builder.Save();
1133 builder.Translate(100, 100);
1134 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1135 auto linear =
1136 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1137 stops, flutter::DlTileMode::kRepeat);
1138 paint.setColorSource(linear);
1139 builder.DrawPaint(paint);
1140 builder.Restore();
1141
1142 builder.Save();
1143 builder.Translate(500, 100);
1144 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1145 auto radial = flutter::DlColorSource::MakeRadial(
1146 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1147 paint.setColorSource(radial);
1148 builder.DrawPaint(paint);
1149 builder.Restore();
1150
1151 builder.Save();
1152 builder.Translate(100, 500);
1153 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1154 auto sweep =
1155 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1156 stops, flutter::DlTileMode::kRepeat);
1157 paint.setColorSource(sweep);
1158 builder.DrawPaint(paint);
1159 builder.Restore();
1160
1161 builder.Save();
1162 builder.Translate(500, 500);
1163 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1164 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1165 auto image = std::make_shared<flutter::DlImageColorSource>(
1166 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1167 flutter::DlTileMode::kRepeat);
1168 paint.setColorSource(image);
1169 builder.DrawPaint(paint);
1170 builder.Restore();
1171
1172 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1173 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [283/454]

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 }

## ◆ TEST_P() [284/454]

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() [285/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1107 of file dl_unittests.cc.

1107 {
1108 flutter::DlPaint paint;
1109 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1110 flutter::DisplayListBuilder builder;
1111 paint.setColorFilter(
1112 flutter::DlLinearToSrgbGammaColorFilter::kInstance.get());
1113 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1114 builder.Translate(0, 200);
1115
1116 paint.setColorFilter(
1117 flutter::DlSrgbToLinearGammaColorFilter::kInstance.get());
1118 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1119
1120 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1121 }

## ◆ TEST_P() [286/454]

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.

## ◆ TEST_P() [287/454]

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 }

## ◆ TEST_P() [288/454]

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() [289/454]

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 }

## ◆ TEST_P() [290/454]

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() [291/454]

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

## ◆ TEST_P() [292/454]

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

## ◆ TEST_P() [293/454]

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

## ◆ TEST_P() [294/454]

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

## ◆ TEST_P() [295/454]

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

## ◆ TEST_P() [296/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 947 of file dl_unittests.cc.

947 {
948 auto boston = CreateTextureForFixture("boston.jpg");
949
950 auto callback = [&]() {
951 static int selected_matrix_type = 0;
952 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
953
954 static float ctm_translation[2] = {200, 200};
955 static float ctm_scale[2] = {0.65, 0.65};
956 static float ctm_skew[2] = {0, 0};
957
958 static bool enable = true;
959 static float translation[2] = {100, 100};
960 static float scale[2] = {0.8, 0.8};
961 static float skew[2] = {0.2, 0.2};
962
963 static bool enable_savelayer = true;
964
965 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
966 {
967 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
968 sizeof(matrix_type_names) / sizeof(char*));
969
970 ImGui::TextWrapped("Current Transform");
971 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
972 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
973 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
974
975 ImGui::TextWrapped(
976 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
977 "The only difference is that MatrixFilter doesn't affect the effect "
978 "transform, whereas LocalMatrixFilter does.");
979 // Note: See this behavior in:
980 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
981 ImGui::Checkbox("Enable", &enable);
982 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
983 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
984 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
985
986 ImGui::TextWrapped(
987 "Rendering the filtered image within a layer can expose bounds "
988 "issues. If the rendered image gets cut off when this setting is "
989 "enabled, there's a coverage bug in the filter.");
990 ImGui::Checkbox("Render in layer", &enable_savelayer);
991 }
992 ImGui::End();
993
994 flutter::DisplayListBuilder builder;
995 flutter::DlPaint paint;
996
997 if (enable_savelayer) {
998 builder.SaveLayer(nullptr, nullptr);
999 }
1000 {
1001 auto content_scale = GetContentScale();
1002 builder.Scale(content_scale.x, content_scale.y);
1003
1004 // Set the current transform
1005 auto ctm_matrix =
1006 SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
1007 ctm_skew[1], ctm_scale[1], ctm_translation[1], //
1008 0, 0, 1);
1009 builder.Transform(ctm_matrix);
1010
1011 // Set the matrix filter
1012 auto filter_matrix =
1013 SkMatrix::MakeAll(scale[0], skew[0], translation[0], //
1014 skew[1], scale[1], translation[1], //
1015 0, 0, 1);
1016
1017 if (enable) {
1018 switch (selected_matrix_type) {
1019 case 0: {
1020 auto filter = flutter::DlMatrixImageFilter(
1021 filter_matrix, flutter::DlImageSampling::kLinear);
1022 paint.setImageFilter(&filter);
1023 break;
1024 }
1025 case 1: {
1026 auto internal_filter =
1027 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1028 .shared();
1029 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1030 internal_filter);
1031 paint.setImageFilter(&filter);
1032 break;
1033 }
1034 }
1035 }
1036
1037 builder.DrawImage(DlImageImpeller::Make(boston), {},
1038 flutter::DlImageSampling::kLinear, &paint);
1039 }
1040 if (enable_savelayer) {
1041 builder.Restore();
1042 }
1043
1044 return builder.Build();
1045 };
1046
1047 ASSERT_TRUE(OpenPlaygroundHere(callback));
1048 }

References impeller::DlImageImpeller::Make(), and scale.

## ◆ TEST_P() [297/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1050 of file dl_unittests.cc.

1050 {
1051 auto callback = [&]() {
1052 static float translation[2] = {0, 0};
1053 static bool enable_save_layer = true;
1054
1055 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1056 ImGui::SliderFloat2("Translation", translation, -130, 130);
1057 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1058 ImGui::End();
1059
1060 flutter::DisplayListBuilder builder;
1061 builder.Save();
1062 builder.Scale(2.0, 2.0);
1063 flutter::DlPaint paint;
1064 paint.setColor(flutter::DlColor::kYellow());
1065 builder.DrawRect(SkRect::MakeWH(300, 300), paint);
1066 paint.setStrokeWidth(1.0);
1067 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1068 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1069 builder.DrawLine(SkPoint::Make(150, 0), SkPoint::Make(150, 300), paint);
1070 builder.DrawLine(SkPoint::Make(0, 150), SkPoint::Make(300, 150), paint);
1071
1072 flutter::DlPaint save_paint;
1073 SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
1074 SkMatrix translate_matrix =
1075 SkMatrix::Translate(translation[0], translation[1]);
1076 if (enable_save_layer) {
1077 auto filter = flutter::DlMatrixImageFilter(
1078 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1079 save_paint.setImageFilter(filter.shared());
1080 builder.SaveLayer(&bounds, &save_paint);
1081 } else {
1082 builder.Save();
1083 builder.Transform(translate_matrix);
1084 }
1085
1086 SkMatrix filter_matrix = SkMatrix::I();
1087 filter_matrix.postTranslate(-150, -150);
1088 filter_matrix.postScale(0.2f, 0.2f);
1089 filter_matrix.postTranslate(150, 150);
1090 auto filter = flutter::DlMatrixImageFilter(
1091 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1092
1093 save_paint.setImageFilter(filter.shared());
1094
1095 builder.SaveLayer(&bounds, &save_paint);
1096 flutter::DlPaint paint2;
1097 paint2.setColor(flutter::DlColor::kBlue());
1098 builder.DrawRect(bounds, paint2);
1099 builder.Restore();
1100 builder.Restore();
1101 return builder.Build();
1102 };
1103
1104 ASSERT_TRUE(OpenPlaygroundHere(callback));
1105 }

## ◆ TEST_P() [298/454]

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 }

## ◆ TEST_P() [299/454]

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 }

## ◆ TEST_P() [300/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 913 of file dl_unittests.cc.

913 {
914 flutter::DisplayListBuilder builder;
915 std::vector<flutter::DlStrokeCap> caps = {
916 flutter::DlStrokeCap::kButt,
917 flutter::DlStrokeCap::kRound,
918 flutter::DlStrokeCap::kSquare,
919 };
920 flutter::DlPaint paint = //
921 flutter::DlPaint() //
922 .setColor(flutter::DlColor::kWhite()) //
923 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
924 .setStrokeWidth(0);
925 flutter::DlPaint outline_paint = //
926 flutter::DlPaint() //
927 .setColor(flutter::DlColor::kYellow()) //
928 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
929 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
930 .setStrokeWidth(1);
931 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
932 for (auto cap : caps) {
933 paint.setStrokeCap(cap);
934 builder.DrawLine({50, 50}, {60, 50}, paint);
935 builder.DrawRect({45, 45, 65, 55}, outline_paint);
936 builder.DrawLine({100, 50}, {100, 50}, paint);
937 if (cap != flutter::DlStrokeCap::kButt) {
938 builder.DrawRect({95, 45, 105, 55}, outline_paint);
939 }
940 builder.DrawPath(path, paint);
941 builder.DrawRect(path.getBounds().makeOutset(5, 5), outline_paint);
942 builder.Translate(0, 150);
943 }
944 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
945 }

## ◆ TEST_P() [301/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1330 of file dl_unittests.cc.

1330 {
1331 flutter::DisplayListBuilder builder;
1332
1333 flutter::DlPaint fill_paint = //
1334 flutter::DlPaint() //
1335 .setColor(flutter::DlColor::kBlue()) //
1336 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1337 .setStrokeWidth(10);
1338 flutter::DlPaint stroke_paint = //
1339 flutter::DlPaint() //
1340 .setColor(flutter::DlColor::kGreen()) //
1341 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1342 .setStrokeWidth(10);
1343
1344 builder.DrawRRect(
1345 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1346 fill_paint);
1347 builder.DrawRRect(
1348 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1349 stroke_paint);
1350
1351 builder.DrawRRect(
1352 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1353 fill_paint);
1354 builder.DrawRRect(
1355 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1356 stroke_paint);
1357
1358 flutter::DlPaint reference_paint = //
1359 flutter::DlPaint() //
1360 .setColor(flutter::DlColor::kMidGrey()) //
1361 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1362 .setStrokeWidth(10);
1363
1364 builder.DrawRRect(
1365 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1366 reference_paint);
1367 builder.DrawRRect(
1368 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1369 reference_paint);
1370
1371 flutter::DlPaint clip_fill_paint = //
1372 flutter::DlPaint() //
1373 .setColor(flutter::DlColor::kCyan()) //
1374 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1375 .setStrokeWidth(10);
1376
1377 builder.Save();
1378 builder.ClipRRect(
1379 SkRRect::MakeRectXY(SkRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1380 builder.DrawPaint(clip_fill_paint);
1381 builder.Restore();
1382
1383 builder.Save();
1384 builder.ClipRRect(
1385 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1386 builder.DrawPaint(clip_fill_paint);
1387 builder.Restore();
1388
1389 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1390 }

## ◆ TEST_P() [302/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawMaskBlursThatMightUseSaveLayers |
| ) |  |

Definition at line 1506 of file dl_unittests.cc.

1506 {
1507 flutter::DisplayListBuilder builder;
1508 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1509 Vector2 scale = GetContentScale();
1510 builder.Scale(scale.x, scale.y);
1511
1512 builder.Save();
1513 // We need a small transform op to avoid a deferred save
1514 builder.Translate(1.0f, 1.0f);
1515 auto solid_filter =
1516 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1517 flutter::DlPaint solid_alpha_paint =
1518 flutter::DlPaint() //
1519 .setMaskFilter(solid_filter) //
1520 .setColor(flutter::DlColor::kBlue()) //
1521 .setAlpha(0x7f);
1522 for (int x = 1; x <= 4; x++) {
1523 for (int y = 1; y <= 4; y++) {
1524 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1525 solid_alpha_paint);
1526 }
1527 }
1528 builder.Restore();
1529
1530 builder.Save();
1531 builder.Translate(500.0f, 0.0f);
1532 auto normal_filter =
1533 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1534 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1535 SkMatrix::RotateDeg(10), flutter::DlImageSampling::kLinear);
1536 flutter::DlPaint normal_if_paint =
1537 flutter::DlPaint() //
1538 .setMaskFilter(solid_filter) //
1539 .setImageFilter(rotate_if) //
1540 .setColor(flutter::DlColor::kGreen()) //
1541 .setAlpha(0x7f);
1542 for (int x = 1; x <= 4; x++) {
1543 for (int y = 1; y <= 4; y++) {
1544 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1545 normal_if_paint);
1546 }
1547 }
1548 builder.Restore();
1549
1550 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1551 }

References scale.

## ◆ TEST_P() [303/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1483 of file dl_unittests.cc.

1483 {
1484 flutter::DisplayListBuilder builder;
1485 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1486
1487 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1488 builder.DrawCircle({300, 300}, 200,
1489 flutter::DlPaint().setMaskFilter(&filter));
1490
1491 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1492 flutter::DlColor::kGreen()};
1493 const float stops[2] = {0.0, 1.0};
1494 auto linear = flutter::DlColorSource::MakeLinear(
1495 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1496 flutter::DlTileMode::kRepeat);
1497 flutter::DlPaint blend_paint =
1498 flutter::DlPaint() //
1499 .setColorSource(linear) //
1500 .setBlendMode(flutter::DlBlendMode::kScreen);
1501 builder.DrawPaint(blend_paint);
1502
1503 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1504 }

## ◆ TEST_P() [304/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1292 of file dl_unittests.cc.

1292 {
1293 flutter::DisplayListBuilder builder;
1294 std::vector<flutter::DlStrokeJoin> joins = {
1295 flutter::DlStrokeJoin::kBevel,
1296 flutter::DlStrokeJoin::kRound,
1297 flutter::DlStrokeJoin::kMiter,
1298 };
1299 flutter::DlPaint paint = //
1300 flutter::DlPaint() //
1301 .setColor(flutter::DlColor::kWhite()) //
1302 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1303 .setStrokeWidth(10);
1304 flutter::DlPaint stroke_paint = //
1305 flutter::DlPaint() //
1306 .setColor(flutter::DlColor::kWhite()) //
1307 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1308 .setStrokeWidth(10);
1309 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1310
1311 builder.Translate(300, 50);
1312 builder.Scale(0.8, 0.8);
1313 for (auto join : joins) {
1314 paint.setStrokeJoin(join);
1315 stroke_paint.setStrokeJoin(join);
1316 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1317 builder.DrawRect(SkRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1318 builder.DrawRRect(
1319 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 0, 100, 100), 30, 30), paint);
1320 builder.DrawRRect(
1321 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1322 stroke_paint);
1323 builder.DrawCircle({350, 50}, 50, paint);
1324 builder.DrawCircle({350, 200}, 50, stroke_paint);
1325 builder.Translate(0, 300);
1326 }
1327 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1328 }

## ◆ TEST_P() [305/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1392 of file dl_unittests.cc.

1392 {
1393 std::vector<const char*> blend_mode_names;
1394 std::vector<flutter::DlBlendMode> blend_mode_values;
1395 {
1396 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1397 // Pipeline blends (Porter-Duff alpha compositing)
1398 {"Clear", flutter::DlBlendMode::kClear},
1399 {"Source", flutter::DlBlendMode::kSrc},
1400 {"Destination", flutter::DlBlendMode::kDst},
1401 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1402 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1403 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1404 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1405 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1406 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1407 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1408 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1409 {"Xor", flutter::DlBlendMode::kXor},
1410 {"Plus", flutter::DlBlendMode::kPlus},
1411 {"Modulate", flutter::DlBlendMode::kModulate},
1412 // Advanced blends (color component blends)
1413 {"Screen", flutter::DlBlendMode::kScreen},
1414 {"Overlay", flutter::DlBlendMode::kOverlay},
1415 {"Darken", flutter::DlBlendMode::kDarken},
1416 {"Lighten", flutter::DlBlendMode::kLighten},
1417 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1418 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1419 {"HardLight", flutter::DlBlendMode::kHardLight},
1420 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1421 {"Difference", flutter::DlBlendMode::kDifference},
1422 {"Exclusion", flutter::DlBlendMode::kExclusion},
1423 {"Multiply", flutter::DlBlendMode::kMultiply},
1424 {"Hue", flutter::DlBlendMode::kHue},
1425 {"Saturation", flutter::DlBlendMode::kSaturation},
1426 {"Color", flutter::DlBlendMode::kColor},
1427 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1428 };
1429 assert(blends.size() ==
1430 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1431 for (const auto& [name, mode] : blends) {
1432 blend_mode_names.push_back(name);
1433 blend_mode_values.push_back(mode);
1434 }
1435 }
1436
1437 auto callback = [&]() {
1438 static int current_blend_index = 3;
1439 static float dst_alpha = 1;
1440 static float src_alpha = 1;
1441 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1442 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1443 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1444 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1445
1446 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1447 {
1448 ImGui::ListBox("Blending mode", &current_blend_index,
1449 blend_mode_names.data(), blend_mode_names.size());
1450 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1451 ImGui::ColorEdit4("Color A", color0);
1452 ImGui::ColorEdit4("Color B", color1);
1453 ImGui::ColorEdit4("Color C", color2);
1454 ImGui::ColorEdit4("Source Color", src_color);
1455 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1456 }
1457 ImGui::End();
1458
1459 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1460 SkPoint::Make(200, 100),
1461 SkPoint::Make(300, 300)};
1462 std::vector<flutter::DlColor> colors = {
1463 toColor(color0).modulateOpacity(dst_alpha),
1464 toColor(color1).modulateOpacity(dst_alpha),
1465 toColor(color2).modulateOpacity(dst_alpha)};
1466
1467 auto vertices = flutter::DlVertices::Make(
1468 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1469 /*texture_coordinates=*/nullptr, colors.data());
1470
1471 flutter::DisplayListBuilder builder;
1472 flutter::DlPaint paint;
1473
1474 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1475 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1476 paint);
1477 return builder.Build();
1478 };
1479
1480 ASSERT_TRUE(OpenPlaygroundHere(callback));
1481 }

References toColor().

## ◆ TEST_P() [306/454]

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

## ◆ TEST_P() [307/454]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1255 of file dl_unittests.cc.

1255 {
1256 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1257 flutter::DlBlurStyle::kNormal, 10);
1258
1259 flutter::DisplayListBuilder builder;
1260
1261 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1262 flutter::DlColor::kGreen()};
1263 std::array<float, 2> stops = {0, 1};
1264 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1265 std::make_shared<flutter::DlColorColorSource>(flutter::DlColor::kWhite()),
1266 flutter::DlColorSource::MakeLinear(
1267 SkPoint::Make(0, 0), SkPoint::Make(100, 50), 2, colors.data(),
1268 stops.data(), flutter::DlTileMode::kClamp)};
1269
1270 int offset = 100;
1271 for (const auto& color_source : color_sources) {
1272 flutter::DlPaint paint;
1273 paint.setColorSource(color_source);
1274 paint.setMaskFilter(blur_filter);
1275
1276 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1277 builder.DrawRRect(
1278 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, offset, 100, 50), 30, 30),
1279 paint);
1280 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1281 paint.setStrokeWidth(10);
1282 builder.DrawRRect(
1283 SkRRect::MakeRectXY(SkRect::MakeXYWH(300, offset, 100, 50), 30, 30),
1284 paint);
1285
1286 offset += 100;
1287 }
1288
1289 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1290 }

References offset.

## ◆ TEST_P() [308/454]

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() [309/454]

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 stroke_width.

## ◆ TEST_P() [310/454]

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 }

## ◆ TEST_P() [311/454]

impeller::testing::TEST_P | ( | DriverInfoVKTest | ,
|  | CanDumpToLog |
| ) |  |

Definition at line 29 of file driver_info_vk_unittests.cc.

29 {
30 ASSERT_TRUE(GetContext());
31 const auto& driver_info =
32 SurfaceContextVK::Cast(*GetContext()).GetParent()->GetDriverInfo();
33 ASSERT_NE(driver_info, nullptr);
34 fml::testing::LogCapture log;
35 driver_info->DumpToLog();
36 EXPECT_TRUE(log.str().find("Driver Information") != std::string::npos);
37 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), and impeller::SurfaceContextVK::GetParent().

## ◆ TEST_P() [312/454]

impeller::testing::TEST_P | ( | DriverInfoVKTest | ,
|  | CanQueryDriverInfo |
| ) |  |

Definition at line 16 of file driver_info_vk_unittests.cc.

16 {
17 ASSERT_TRUE(GetContext());
18 const auto& driver_info =
19 SurfaceContextVK::Cast(*GetContext()).GetParent()->GetDriverInfo();
20 ASSERT_NE(driver_info, nullptr);
21 // 1.1 is the base Impeller version. The driver can't be lower than that.
22 ASSERT_TRUE(driver_info->GetAPIVersion().IsAtLeast(Version{1, 1, 0}));
23 ASSERT_NE(driver_info->GetVendor(), VendorVK::kUnknown);
24 ASSERT_NE(driver_info->GetDeviceType(), DeviceTypeVK::kUnknown);
25 ASSERT_NE(driver_info->GetDriverName(), "");
26 EXPECT_FALSE(driver_info->IsKnownBadDriver());
27 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::SurfaceContextVK::GetParent(), and impeller::kUnknown.

## ◆ TEST_P() [313/454]

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() [314/454]

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() [315/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 830 of file entity_unittests.cc.

830 {
831 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
832 static float scale = 20;
833
834 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
835 ImGui::SliderFloat("Scale", &scale, 1, 100);
836 ImGui::End();
837
838 Entity entity;
839 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
840 auto path = PathBuilder{}
841 .MoveTo({97.325, 34.818})
842 .CubicCurveTo({98.50862885295136, 34.81812293973836},
843 {99.46822048142015, 33.85863261475589},
844 {99.46822048142015, 32.67499810206613})
845 .CubicCurveTo({99.46822048142015, 31.491363589376355},
846 {98.50862885295136, 30.53187326439389},
847 {97.32499434685802, 30.531998226542708})
848 .CubicCurveTo({96.14153655073771, 30.532123170035373},
849 {95.18222070648729, 31.491540299350355},
850 {95.18222070648729, 32.67499810206613})
851 .CubicCurveTo({95.18222070648729, 33.85845590478189},
852 {96.14153655073771, 34.81787303409686},
853 {97.32499434685802, 34.81799797758954})
854 .Close()
855 .TakePath();
856 entity.SetTransform(
857 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
858
859 static std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
860
861 auto contents = std::make_shared<SolidColorContents>();
862 contents->SetColor(Color::Red());
863 contents->SetGeometry(geom.get());
864
865 entity.SetContents(contents);
866 return entity.Render(context, pass);
867 };
868 ASSERT_TRUE(OpenPlaygroundHere(callback));
869 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), scale, impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [316/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 699 of file entity_unittests.cc.

699 {
700 std::vector<const char*> blend_mode_names;
701 std::vector<BlendMode> blend_mode_values;
702 {
703 // Force an exhausiveness check with a switch. When adding blend modes,
704 // update this switch with a new name/value to make it selectable in the
705 // test GUI.
706
707 const BlendMode b{};
708 static_assert(b == BlendMode::kClear); // Ensure the first item in
709 // the switch is the first
710 // item in the enum.
711 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
712 switch (b) {
713 case BlendMode::kClear:
714 blend_mode_names.push_back("Clear");
715 blend_mode_values.push_back(BlendMode::kClear);
716 case BlendMode::kSource:
717 blend_mode_names.push_back("Source");
718 blend_mode_values.push_back(BlendMode::kSource);
719 case BlendMode::kDestination:
720 blend_mode_names.push_back("Destination");
721 blend_mode_values.push_back(BlendMode::kDestination);
722 case BlendMode::kSourceOver:
723 blend_mode_names.push_back("SourceOver");
724 blend_mode_values.push_back(BlendMode::kSourceOver);
725 case BlendMode::kDestinationOver:
726 blend_mode_names.push_back("DestinationOver");
727 blend_mode_values.push_back(BlendMode::kDestinationOver);
728 case BlendMode::kSourceIn:
729 blend_mode_names.push_back("SourceIn");
730 blend_mode_values.push_back(BlendMode::kSourceIn);
731 case BlendMode::kDestinationIn:
732 blend_mode_names.push_back("DestinationIn");
733 blend_mode_values.push_back(BlendMode::kDestinationIn);
734 case BlendMode::kSourceOut:
735 blend_mode_names.push_back("SourceOut");
736 blend_mode_values.push_back(BlendMode::kSourceOut);
737 case BlendMode::kDestinationOut:
738 blend_mode_names.push_back("DestinationOut");
739 blend_mode_values.push_back(BlendMode::kDestinationOut);
740 case BlendMode::kSourceATop:
741 blend_mode_names.push_back("SourceATop");
742 blend_mode_values.push_back(BlendMode::kSourceATop);
743 case BlendMode::kDestinationATop:
744 blend_mode_names.push_back("DestinationATop");
745 blend_mode_values.push_back(BlendMode::kDestinationATop);
746 case BlendMode::kXor:
747 blend_mode_names.push_back("Xor");
748 blend_mode_values.push_back(BlendMode::kXor);
749 case BlendMode::kPlus:
750 blend_mode_names.push_back("Plus");
751 blend_mode_values.push_back(BlendMode::kPlus);
752 case BlendMode::kModulate:
753 blend_mode_names.push_back("Modulate");
754 blend_mode_values.push_back(BlendMode::kModulate);
755 };
756 }
757
758 auto callback = [&](ContentContext& context, RenderPass& pass) {
759 auto world_matrix = Matrix::MakeScale(GetContentScale());
760 auto draw_rect = [&context, &pass, &world_matrix](
761 Rect rect, Color color, BlendMode blend_mode) -> bool {
762 using VS = SolidFillPipeline::VertexShader;
763 using FS = SolidFillPipeline::FragmentShader;
764
765 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
766 {
767 auto r = rect.GetLTRB();
768 vtx_builder.AddVertices({
769 {Point(r[0], r[1])},
770 {Point(r[2], r[1])},
771 {Point(r[2], r[3])},
772 {Point(r[0], r[1])},
773 {Point(r[2], r[3])},
774 {Point(r[0], r[3])},
775 });
776 }
777
778 pass.SetCommandLabel("Blended Rectangle");
779 auto options = OptionsFromPass(pass);
780 options.blend_mode = blend_mode;
781 options.primitive_type = PrimitiveType::kTriangle;
782 pass.SetPipeline(context.GetSolidFillPipeline(options));
783 pass.SetVertexBuffer(
784 vtx_builder.CreateVertexBuffer(context.GetTransientsBuffer()));
785
786 VS::FrameInfo frame_info;
787 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
788 VS::BindFrameInfo(
789 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
790 FS::FragInfo frag_info;
791 frag_info.color = color.Premultiply();
792 FS::BindFragInfo(
793 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
794 return pass.Draw().ok();
795 };
796
797 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
798 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
799 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
800 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
801 static int current_blend_index = 3;
802 ImGui::ListBox("Blending mode", &current_blend_index,
803 blend_mode_names.data(), blend_mode_names.size());
804 ImGui::End();
805
806 BlendMode selected_mode = blend_mode_values[current_blend_index];
807
808 Point a, b, c, d;
809 static PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
810 static PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
811 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
812 static PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
813 static PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
814 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
815
816 bool result = true;
817 result = result &&
818 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
819 pass.GetRenderTargetSize().height),
820 Color(), BlendMode::kClear);
821 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
822 BlendMode::kSourceOver);
823 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
824 selected_mode);
825 return result;
826 };
827 ASSERT_TRUE(OpenPlaygroundHere(callback));
828 }

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() [317/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1257 of file entity_unittests.cc.

1257 {
1258 auto fill = std::make_shared<SolidColorContents>();
1259 auto geom = Geometry::MakeFillPath(
1260 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1261 fill->SetGeometry(geom.get());
1262 fill->SetColor(Color::CornflowerBlue());
1263 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1264 FilterInput::Make(fill), Radius{3}, Radius{4});
1265
1266 {
1267 Entity e;
1268 e.SetTransform(Matrix());
1269 auto actual = border_mask_blur->GetCoverage(e);
1270 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1271 ASSERT_TRUE(actual.has_value());
1272 ASSERT_RECT_NEAR(actual.value(), expected);
1273 }
1274
1275 {
1276 Entity e;
1277 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1278 auto actual = border_mask_blur->GetCoverage(e);
1279 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1280 ASSERT_TRUE(actual.has_value());
1281 ASSERT_RECT_NEAR(actual.value(), expected);
1282 }
1283 }

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() [318/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2325 of file entity_unittests.cc.

2325 {
2326 PathBuilder builder = {};
2327 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2328 Path path = builder.TakePath();
2329
2330 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2331
2332 auto geom = Geometry::MakeFillPath(path);
2333
2334 Entity entity;
2335 RenderTarget target =
2336 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2337 *GetContext(), {1, 1}, 1u);
2338 testing::MockRenderPass render_pass(GetContext(), target);
2339 auto position_result =
2340 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2341
2342 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2343
2344 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2345 }

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

## ◆ TEST_P() [319/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 68 of file entity_unittests.cc.

68 {
69 Entity entity;
70 ASSERT_TRUE(entity.GetTransform().IsIdentity());
71 }

References impeller::Entity::GetTransform(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [320/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 367 of file entity_unittests.cc.

367 {
368 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
369 const char* input_axis[] = {"X", "Y", "Z"};
370 static int rotation_axis_index = 0;
371 static float rotation = 0;
372 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
373 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
374 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
375 sizeof(input_axis) / sizeof(char*));
376 Matrix rotation_matrix;
377 switch (rotation_axis_index) {
378 case 0:
379 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
380 break;
381 case 1:
382 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
383 break;
384 case 2:
385 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
386 break;
387 default:
388 rotation_matrix = Matrix{};
389 break;
390 }
391
392 if (ImGui::Button("Reset")) {
393 rotation = 0;
394 }
395 ImGui::End();
396 Matrix current_transform =
397 Matrix::MakeScale(GetContentScale())
398 .MakeTranslation(
399 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
400 pass.GetRenderTargetSize().height / 2.0)));
401 Matrix result_transform = current_transform * rotation_matrix;
402 Path path =
403 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
404
405 Entity entity;
406 entity.SetTransform(result_transform);
407
408 static std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
409
410 auto contents = std::make_shared<SolidColorContents>();
411 contents->SetColor(Color::Red());
412 contents->SetGeometry(geom.get());
413
414 entity.SetContents(contents);
415 return entity.Render(context, pass);
416 };
417 ASSERT_TRUE(OpenPlaygroundHere(callback));
418 }

References impeller::PathBuilder::AddRect(), impeller::kPi, impeller::Geometry::MakeFillPath(), 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() [321/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2347 of file entity_unittests.cc.

2347 {
2348 PathBuilder builder = {};
2349 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2350 Path path = builder.TakePath();
2351
2352 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2353
2354 auto contents = std::make_shared<SolidColorContents>();
2355 static std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
2356 contents->SetGeometry(geom.get());
2357 contents->SetColor(Color::Red());
2358
2359 Entity entity;
2360 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2361 entity.SetContents(contents);
2362
2363 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2364 }

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() [322/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsGetClipCoverageIsCorrect |
| ) |  |

Definition at line 1331 of file entity_unittests.cc.

1331 {
1332 // Intersection: No stencil coverage, no geometry.
1333 {
1334 auto clip = std::make_shared<ClipContents>();
1335 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1336 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1337
1338 ASSERT_FALSE(result.coverage.has_value());
1339 }
1340
1341 // Intersection: No stencil coverage, with geometry.
1342 {
1343 auto clip = std::make_shared<ClipContents>();
1344 auto geom = Geometry::MakeFillPath(
1345 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath());
1346 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1347 clip->SetGeometry(geom.get());
1348 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1349
1350 ASSERT_FALSE(result.coverage.has_value());
1351 }
1352
1353 // Intersection: With stencil coverage, no geometry.
1354 {
1355 auto clip = std::make_shared<ClipContents>();
1356 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1357 auto result =
1358 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1359
1360 ASSERT_FALSE(result.coverage.has_value());
1361 }
1362
1363 // Intersection: With stencil coverage, with geometry.
1364 {
1365 auto clip = std::make_shared<ClipContents>();
1366 auto geom = Geometry::MakeFillPath(
1367 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath());
1368 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1369 clip->SetGeometry(geom.get());
1370 auto result =
1371 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1372
1373 ASSERT_TRUE(result.coverage.has_value());
1374 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
1375 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1376 }
1377
1378 // Difference: With stencil coverage, with geometry.
1379 {
1380 auto clip = std::make_shared<ClipContents>();
1381 auto geom = Geometry::MakeFillPath(
1382 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath());
1383 clip->SetClipOperation(Entity::ClipOperation::kDifference);
1384 clip->SetGeometry(geom.get());
1385 auto result =
1386 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1387
1388 ASSERT_TRUE(result.coverage.has_value());
1389 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
1390 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1391 }
1392 }

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() [323/454]

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 auto geom = Geometry::MakeCover();
41 contents->SetGeometry(geom.get());
42
43 Entity entity;
44 entity.SetContents(std::move(contents));
45
46 // Render the clip contents.
47
48 ASSERT_TRUE(recording_pass->GetCommands().empty());
49 ASSERT_TRUE(entity.Render(*content_context, *recording_pass));
50 ASSERT_FALSE(recording_pass->GetCommands().empty());
51 }

References impeller::Entity::kIntersect, impeller::Geometry::MakeCover(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [324/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2166 of file entity_unittests.cc.

2166 {
2167 Entity entity;
2168 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2169 auto src_contents = std::make_shared<SolidColorContents>();
2170 auto src_geom = Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000));
2171 src_contents->SetGeometry(src_geom.get());
2172 src_contents->SetColor(Color::Red());
2173
2174 auto dst_contents = std::make_shared<SolidColorContents>();
2175 auto dst_geom = Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000));
2176 dst_contents->SetGeometry(dst_geom.get());
2177 dst_contents->SetColor(Color::Blue());
2178
2179 auto contents = ColorFilterContents::MakeBlend(
2180 BlendMode::kSourceOver, {FilterInput::Make(dst_contents, false),
2181 FilterInput::Make(src_contents, false)});
2182 entity.SetContents(std::move(contents));
2183 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2184 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 1933 of file entity_unittests.cc.

1933 {
1934 auto image = CreateTextureForFixture("boston.jpg");
1935 auto filter = ColorFilterContents::MakeBlend(
1936 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
1937
1938 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1939 Entity entity;
1940 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1941 Matrix::MakeTranslation({500, 300}) *
1942 Matrix::MakeScale(Vector2{0.5, 0.5}));
1943 entity.SetContents(filter);
1944 return entity.Render(context, pass);
1945 };
1946 ASSERT_TRUE(OpenPlaygroundHere(callback));
1947 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 1949 of file entity_unittests.cc.

1949 {
1950 auto image = CreateTextureForFixture("boston.jpg");
1951 auto filter = ColorFilterContents::MakeBlend(
1952 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
1953
1954 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1955 Entity entity;
1956 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1957 Matrix::MakeTranslation({500, 300}) *
1958 Matrix::MakeScale(Vector2{0.5, 0.5}));
1959 entity.SetContents(filter);
1960 return entity.Render(context, pass);
1961 };
1962 ASSERT_TRUE(OpenPlaygroundHere(callback));
1963 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 1981 of file entity_unittests.cc.

1981 {
1982 auto image = CreateTextureForFixture("boston.jpg");
1983 auto filter = ColorFilterContents::MakeBlend(
1984 BlendMode::kDestination, FilterInput::Make({image}), Color::Red());
1985
1986 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1987 Entity entity;
1988 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1989 Matrix::MakeTranslation({500, 300}) *
1990 Matrix::MakeScale(Vector2{0.5, 0.5}));
1991 entity.SetContents(filter);
1992 return entity.Render(context, pass);
1993 };
1994 ASSERT_TRUE(OpenPlaygroundHere(callback));
1995 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 1965 of file entity_unittests.cc.

1965 {
1966 auto image = CreateTextureForFixture("boston.jpg");
1967 auto filter = ColorFilterContents::MakeBlend(
1968 BlendMode::kSource, FilterInput::Make({image}), Color::Red());
1969
1970 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1971 Entity entity;
1972 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1973 Matrix::MakeTranslation({500, 300}) *
1974 Matrix::MakeScale(Vector2{0.5, 0.5}));
1975 entity.SetContents(filter);
1976 return entity.Render(context, pass);
1977 };
1978 ASSERT_TRUE(OpenPlaygroundHere(callback));
1979 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 1997 of file entity_unittests.cc.

1997 {
1998 auto image = CreateTextureForFixture("boston.jpg");
1999 auto filter = ColorFilterContents::MakeBlend(
2000 BlendMode::kSourceIn, FilterInput::Make({image}), Color::Red());
2001
2002 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2003 Entity entity;
2004 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2005 Matrix::MakeTranslation({500, 300}) *
2006 Matrix::MakeScale(Vector2{0.5, 0.5}));
2007 entity.SetContents(filter);
2008 return entity.Render(context, pass);
2009 };
2010 ASSERT_TRUE(OpenPlaygroundHere(callback));
2011 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1448 of file entity_unittests.cc.

1448 {
1449 // Set up a simple color background.
1450 auto fill = std::make_shared<SolidColorContents>();
1451 auto geom = Geometry::MakeFillPath(
1452 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1453 fill->SetGeometry(geom.get());
1454 fill->SetColor(Color::Coral());
1455
1456 // Set the color matrix filter.
1457 ColorMatrix matrix = {
1458 1, 1, 1, 1, 1, //
1459 1, 1, 1, 1, 1, //
1460 1, 1, 1, 1, 1, //
1461 1, 1, 1, 1, 1, //
1462 };
1463
1464 auto filter =
1465 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1466
1467 Entity e;
1468 e.SetTransform(Matrix());
1469
1470 // Confirm that the actual filter coverage matches the expected coverage.
1471 auto actual = filter->GetCoverage(e);
1472 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1473
1474 ASSERT_TRUE(actual.has_value());
1475 ASSERT_RECT_NEAR(actual.value(), expected);
1476 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1478 of file entity_unittests.cc.

1478 {
1479 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1480 ASSERT_TRUE(bay_bridge);
1481
1482 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1483 // UI state.
1484 static ColorMatrix color_matrix = {
1485 1, 0, 0, 0, 0, //
1486 0, 3, 0, 0, 0, //
1487 0, 0, 1, 0, 0, //
1488 0, 0, 0, 1, 0, //
1489 };
1490 static float offset[2] = {500, 400};
1491 static float rotation = 0;
1492 static float scale[2] = {0.65, 0.65};
1493 static float skew[2] = {0, 0};
1494
1495 // Define the ImGui
1496 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1497 {
1498 std::string label = "##1";
1499 for (int i = 0; i < 20; i += 5) {
1500 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1501 &(color_matrix.array[i]), 5, nullptr, nullptr,
1502 "%.2f", 0);
1503 label[2]++;
1504 }
1505
1506 ImGui::SliderFloat2("Translation", &offset[0], 0,
1507 pass.GetRenderTargetSize().width);
1508 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1509 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1510 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1511 }
1512 ImGui::End();
1513
1514 // Set the color matrix filter.
1515 auto filter = ColorFilterContents::MakeColorMatrix(
1516 FilterInput::Make(bay_bridge), color_matrix);
1517
1518 // Define the entity with the color matrix filter.
1519 Entity entity;
1520 entity.SetTransform(
1521 Matrix::MakeScale(GetContentScale()) *
1522 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1523 Matrix::MakeRotationZ(Radians(rotation)) *
1524 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1525 Matrix::MakeSkew(skew[0], skew[1]) *
1526 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1527 entity.SetContents(filter);
1528 entity.Render(context, pass);
1529
1530 return true;
1531 };
1532
1533 ASSERT_TRUE(OpenPlaygroundHere(callback));
1534 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2054 of file entity_unittests.cc.

2054 {
2055 Matrix matrix;
2056 ConicalGradientContents contents;
2057 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2058 contents.SetGeometry(geom.get());
2059
2060 contents.SetColors({Color::CornflowerBlue()});
2061 EXPECT_FALSE(contents.IsOpaque(matrix));
2062 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2063 EXPECT_FALSE(contents.IsOpaque(matrix));
2064
2065 // Create stroked path that required alpha coverage.
2066 geom = Geometry::MakeStrokePath(
2067 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2068 /*stroke_width=*/0.05);
2069 contents.SetGeometry(geom.get());
2070 contents.SetColors({Color::CornflowerBlue()});
2071
2072 EXPECT_FALSE(contents.IsOpaque(matrix));
2073 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::Contents::IsOpaque(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::ConicalGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [333/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2233 of file entity_unittests.cc.

2233 {
2234 ContentContextOptions opts;
2235 auto hash_a = ContentContextOptions::Hash{}(opts);
2236
2237 opts.blend_mode = BlendMode::kColorBurn;
2238 auto hash_b = ContentContextOptions::Hash{}(opts);
2239
2240 opts.has_depth_stencil_attachments = false;
2241 auto hash_c = ContentContextOptions::Hash{}(opts);
2242
2243 opts.primitive_type = PrimitiveType::kPoint;
2244 auto hash_d = ContentContextOptions::Hash{}(opts);
2245
2246 EXPECT_NE(hash_a, hash_b);
2247 EXPECT_NE(hash_b, hash_c);
2248 EXPECT_NE(hash_c, hash_d);
2249 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::kColorBurn, impeller::kPoint, and impeller::ContentContextOptions::primitive_type.

## ◆ TEST_P() [334/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1195 of file entity_unittests.cc.

1195 {
1196 Entity entity;
1197 entity.SetContents(std::make_shared<SolidColorContents>());
1198 ASSERT_FALSE(entity.GetCoverage().has_value());
1199 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [335/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2013 of file entity_unittests.cc.

2013 {
2014 auto arrow_head = PathBuilder{}
2015 .MoveTo({50, 120})
2016 .LineTo({120, 190})
2017 .LineTo({190, 120})
2018 .TakePath();
2019 auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound,
2020 Join::kRound);
2021
2022 auto transform = Matrix::MakeTranslation({300, 300}) *
2023 Matrix::MakeRotationZ(Radians(kPiOver2));
2024 // Note that e[0][0] used to be tested here, but it was -epsilon solely
2025 // due to floating point inaccuracy in the transcendental trig functions.
2026 // e[1][0] is the intended negative value that we care about (-1.0) as it
2027 // comes from the rotation of pi/2.
2028 EXPECT_LT(transform.e[1][0], 0.0f);
2029 auto coverage = geometry->GetCoverage(transform);
2030 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2031 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 420 of file entity_unittests.cc.

420 {
421 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
422 Path path =
423 PathBuilder{}
424 .MoveTo({359.934, 96.6335})
425 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
426 {354.673, 96.8895})
427 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
428 {354.367, 96.9075})
429 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
430 {349.259, 97.2355})
431 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
432 {348.625, 97.2834})
433 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
434 {343.789, 97.6722})
435 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
436 {342.703, 97.7734})
437 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
438 {338.246, 98.207})
439 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
440 {336.612, 98.3894})
441 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
442 {332.623, 98.8476})
443 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
444 {332.237, 98.8982})
445 .LineTo({332.237, 102.601})
446 .LineTo({321.778, 102.601})
447 .LineTo({321.778, 100.382})
448 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
449 {321.161, 100.476})
450 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
451 {315.332, 101.479})
452 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
453 {315.301, 101.484})
454 .LineTo({310.017, 105.94})
455 .LineTo({309.779, 105.427})
456 .LineTo({314.403, 101.651})
457 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
458 {314.368, 101.658})
459 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
460 {308.846, 102.748})
461 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
462 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
463 {303.425, 103.936})
464 .LineTo({299.105, 107.578})
465 .LineTo({298.867, 107.065})
466 .LineTo({302.394, 104.185})
467 .LineTo({302.412, 104.171})
468 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
469 {299.344, 104.921})
470 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
471 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
472 {291.462, 106.979})
473 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
474 {290.471, 107.257})
475 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
476 {287.449, 108.139})
477 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
478 {284.536, 109.035})
479 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
480 {281.952, 109.859})
481 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
482 {279.633, 110.638})
483 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
484 {276.803, 111.607})
485 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
486 {276.672, 111.653})
487 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
488 {271.721, 113.463})
489 .LineTo({271.717, 113.449})
490 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
491 {270.963, 113.628})
492 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
493 {270.748, 113.682})
494 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
495 {269.839, 113.926})
496 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
497 {269.681, 113.972})
498 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
499 {268.756, 114.239})
500 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
501 {268.367, 114.354})
502 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
503 {267.752, 114.54})
504 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
505 {253.564, 119.252})
506 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
507 {253.538, 119.261})
508 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
509 {248.189, 121.131})
510 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
511 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
512 {245.975, 121.912})
513 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
514 {244.698, 122.364})
515 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
516 {242.794, 123.04})
517 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
518 {240.961, 123.693})
519 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
520 {240.052, 124.018})
521 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
522 .LineTo({237.164, 125.003})
523 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
524 {235.81, 125.538})
525 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
526 {234.592, 125.977})
527 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
528 {234.59, 125.977})
529 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
530 {192.381, 141.429})
531 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
532 .LineTo({360, 160})
533 .LineTo({360, 119.256})
534 .LineTo({360, 106.332})
535 .LineTo({360, 96.6307})
536 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
537 {359.934, 96.6335})
538 .Close()
539 .MoveTo({337.336, 124.143})
540 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
541 {338.903, 121.511})
542 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
543 {337.336, 124.143})
544 .Close()
545 .MoveTo({340.082, 121.849})
546 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
547 {340.046, 122.075})
548 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
549 {340.023, 122.177})
550 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
551 {339.952, 122.437})
552 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
553 {339.918, 122.544})
554 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
555 {339.75, 122.938})
556 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
557 {339.74, 122.955})
558 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
559 {339.501, 123.328})
560 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
561 {339.41, 123.438})
562 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
563 {339.145, 123.714})
564 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
565 {339.025, 123.821})
566 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
567 {338.539, 124.143})
568 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
569 {338.58, 123.626})
570 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
571 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
572 {338.704, 123.151})
573 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
574 {338.714, 123.117})
575 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
576 {338.905, 122.712})
577 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
578 {338.922, 122.682})
579 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
580 {339.155, 122.34})
581 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
582 {339.172, 122.319})
583 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
584 {339.425, 122.037})
585 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
586 {339.435, 122.027})
587 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
588 {340.106, 121.511})
589 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
590 {340.082, 121.849})
591 .Close()
592 .MoveTo({340.678, 113.245})
593 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
594 {340.135, 113.775})
595 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
596 {339.115, 114.151})
597 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
598 {336.448, 114.516})
599 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
600 {334.384, 114.513})
601 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
602 {333.605, 114.424})
603 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
604 {331.41, 113.883})
605 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
606 {330.672, 112.813})
607 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
608 {334.526, 113.833})
609 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
610 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
611 {332.76, 110.402})
612 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
613 {335.228, 113.395})
614 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
615 {335.661, 109.592})
616 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
617 {336.07, 113.389})
618 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
619 {338.563, 110.402})
620 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
621 {336.753, 113.784})
622 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
623 {336.796, 113.833})
624 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
625 {340.65, 112.813})
626 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
627 {340.678, 113.245})
628 .Close()
629 .MoveTo({346.357, 106.771})
630 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
631 {347.924, 104.139})
632 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
633 {346.357, 106.771})
634 .Close()
635 .MoveTo({347.56, 106.771})
636 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
637 {349.127, 104.139})
638 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
639 {347.56, 106.771})
640 .Close()
641 .TakePath();
642 Entity entity;
643 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
644
645 static std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
646
647 auto contents = std::make_shared<SolidColorContents>();
648 contents->SetColor(Color::Red());
649 contents->SetGeometry(geom.get());
650
651 entity.SetContents(contents);
652 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
653 }

References impeller::Close(), impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [337/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 338 of file entity_unittests.cc.

338 {
339 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
340 Path path =
341 PathBuilder{}
342 .MoveTo({237.164, 125.003})
343 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
344 {235.81, 125.538})
345 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
346 {234.592, 125.977})
347 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
348 {234.59, 125.977})
349 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
350 {192.381, 141.429})
351 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
352 .Close()
353 .TakePath();
354 Entity entity;
355 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
356
357 static std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
358
359 auto contents = std::make_shared<SolidColorContents>();
360 contents->SetColor(Color::Red());
361 contents->SetGeometry(geom.get());
362
363 entity.SetContents(contents);
364 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
365 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [338/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2217 of file entity_unittests.cc.

2217 {
2218 auto content_context = GetContentContext();
2219 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2220 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2221 });
2222
2223 auto decal_supported = static_cast<Scalar>(
2224 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2225 std::vector<Scalar> expected_constants = {decal_supported};
2226 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2227 expected_constants);
2228 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [339/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawSuperEllipse |
| ) |  |

Definition at line 2366 of file entity_unittests.cc.

2366 {
2367 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2368 // UI state.
2369 static float alpha = 10;
2370 static float beta = 10;
2371 static float radius = 40;
2372 static int degree = 4;
2373 static Color color = Color::Red();
2374
2375 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2376 ImGui::SliderFloat("Alpha", &alpha, 0, 100);
2377 ImGui::SliderFloat("Beta", &beta, 0, 100);
2378 ImGui::SliderInt("Degreee", &degree, 1, 20);
2379 ImGui::SliderFloat("Radius", &radius, 0, 400);
2380 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
2381 ImGui::End();
2382
2383 auto contents = std::make_shared<SolidColorContents>();
2384 static std::unique_ptr<SuperellipseGeometry> geom =
2385 std::make_unique<SuperellipseGeometry>(Point{400, 400}, radius, degree,
2386 alpha, beta);
2387 contents->SetColor(color);
2388 contents->SetGeometry(geom.get());
2389
2390 Entity entity;
2391 entity.SetContents(contents);
2392
2393 return entity.Render(context, pass);
2394 };
2395
2396 ASSERT_TRUE(OpenPlaygroundHere(callback));
2397 }

References color, impeller::Color::Red(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [340/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2311 of file entity_unittests.cc.

2311 {
2312 if (GetParam() != PlaygroundBackend::kVulkan) {
2313 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2314 }
2315 EXPECT_DEATH(
2316 // The easiest way to trigger a validation error is to try to compile
2317 // a shader with an unsupported pixel format.
2318 GetContentContext()->GetBlendColorBurnPipeline({
2319 .color_attachment_pixel_format = PixelFormat::kUnknown,
2320 .has_depth_stencil_attachments = false,
2321 }),
2322 "");
2323 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [341/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2277 of file entity_unittests.cc.

2277 {
2278 RenderTarget target;
2279 testing::MockRenderPass mock_pass(GetContext(), target);
2280
2281 auto get_result = [this, &mock_pass](const Path& path) {
2282 auto geometry = Geometry::MakeFillPath(
2283 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2284 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2285 };
2286
2287 // Convex path
2288 {
2289 GeometryResult result =
2290 get_result(PathBuilder{}
2291 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
2292 .SetConvexity(Convexity::kConvex)
2293 .TakePath());
2294 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2295 }
2296
2297 // Concave path
2298 {
2299 Path path = PathBuilder{}
2300 .MoveTo({0, 0})
2301 .LineTo({100, 0})
2302 .LineTo({100, 100})
2303 .LineTo({50, 50})
2304 .Close()
2305 .TakePath();
2306 GeometryResult result = get_result(path);
2307 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2308 }
2309 }

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() [342/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 73 of file entity_unittests.cc.

73 {
74 auto image = CreateTextureForFixture("boston.jpg");
75 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
76 FilterInput::Make({image}));
77
78 // Without the crop rect (default behavior).
79 {
80 auto actual = filter->GetCoverage({});
81 auto expected = Rect::MakeSize(image->GetSize());
82
83 ASSERT_TRUE(actual.has_value());
84 ASSERT_RECT_NEAR(actual.value(), expected);
85 }
86
87 // With the crop rect.
88 {
89 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
90 filter->SetCoverageHint(expected);
91 auto actual = filter->GetCoverage({});
92
93 ASSERT_TRUE(actual.has_value());
94 ASSERT_RECT_NEAR(actual.value(), expected);
95 }
96 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [343/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 871 of file entity_unittests.cc.

871 {
872 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
873 auto boston = CreateTextureForFixture("boston.jpg");
874 auto kalimba = CreateTextureForFixture("kalimba.jpg");
875 ASSERT_TRUE(bridge && boston && kalimba);
876
877 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
878 auto fi_bridge = FilterInput::Make(bridge);
879 auto fi_boston = FilterInput::Make(boston);
880 auto fi_kalimba = FilterInput::Make(kalimba);
881
882 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
883 BlendMode::kModulate, {fi_kalimba, fi_boston});
884
885 auto blend1 = ColorFilterContents::MakeBlend(
886 BlendMode::kScreen,
887 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
888
889 Entity entity;
890 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
891 Matrix::MakeTranslation({500, 300}) *
892 Matrix::MakeScale(Vector2{0.5, 0.5}));
893 entity.SetContents(blend1);
894 return entity.Render(context, pass);
895 };
896 ASSERT_TRUE(OpenPlaygroundHere(callback));
897 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [344/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 899 of file entity_unittests.cc.

899 {
900 auto boston =
901 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
902 ASSERT_TRUE(boston);
903
904 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
905 const char* input_type_names[] = {"Texture", "Solid Color"};
906 const char* blur_type_names[] = {"Image blur", "Mask blur"};
907 const char* pass_variation_names[] = {"New"};
908 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
909 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
910 const FilterContents::BlurStyle blur_styles[] = {
911 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
912 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
913 const Entity::TileMode tile_modes[] = {
914 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
915 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
916
917 // UI state.
918 static int selected_input_type = 0;
919 static Color input_color = Color::Black();
920 static int selected_blur_type = 0;
921 static int selected_pass_variation = 0;
922 static bool combined_sigma = false;
923 static float blur_amount_coarse[2] = {0, 0};
924 static float blur_amount_fine[2] = {10, 10};
925 static int selected_blur_style = 0;
926 static int selected_tile_mode = 3;
927 static Color cover_color(1, 0, 0, 0.2);
928 static Color bounds_color(0, 1, 0, 0.1);
929 static float offset[2] = {500, 400};
930 static float rotation = 0;
931 static float scale[2] = {0.65, 0.65};
932 static float skew[2] = {0, 0};
933 static float path_rect[4] = {0, 0,
934 static_cast<float>(boston->GetSize().width),
935 static_cast<float>(boston->GetSize().height)};
936
937 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
938 {
939 ImGui::Combo("Input type", &selected_input_type, input_type_names,
940 sizeof(input_type_names) / sizeof(char*));
941 if (selected_input_type == 0) {
942 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
943 } else {
944 ImGui::ColorEdit4("Input color",
945 reinterpret_cast<float*>(&input_color));
946 }
947 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
948 sizeof(blur_type_names) / sizeof(char*));
949 if (selected_blur_type == 0) {
950 ImGui::Combo("Pass variation", &selected_pass_variation,
951 pass_variation_names,
952 sizeof(pass_variation_names) / sizeof(char*));
953 }
954 ImGui::Checkbox("Combined sigma", &combined_sigma);
955 if (combined_sigma) {
956 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
957 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
958 blur_amount_coarse[1] = blur_amount_coarse[0];
959 blur_amount_fine[1] = blur_amount_fine[0];
960 } else {
961 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
962 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
963 }
964 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
965 sizeof(blur_style_names) / sizeof(char*));
966 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
967 sizeof(tile_mode_names) / sizeof(char*));
968 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
969 ImGui::ColorEdit4("Bounds color ",
970 reinterpret_cast<float*>(&bounds_color));
971 ImGui::SliderFloat2("Translation", offset, 0,
972 pass.GetRenderTargetSize().width);
973 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
974 ImGui::SliderFloat2("Scale", scale, 0, 3);
975 ImGui::SliderFloat2("Skew", skew, -3, 3);
976 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
977 }
978 ImGui::End();
979
980 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
981 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
982
983 std::shared_ptr<Contents> input;
984 Size input_size;
985
986 auto input_rect =
987 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
988 if (selected_input_type == 0) {
989 auto texture = std::make_shared<TextureContents>();
990 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
991 texture->SetDestinationRect(input_rect);
992 texture->SetTexture(boston);
993 texture->SetOpacity(input_color.alpha);
994
995 input = texture;
996 input_size = input_rect.GetSize();
997 } else {
998 auto fill = std::make_shared<SolidColorContents>();
999 fill->SetColor(input_color);
1000 static std::unique_ptr<Geometry> geom =
1001 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1002
1003 fill->SetGeometry(geom.get());
1004
1005 input = fill;
1006 input_size = input_rect.GetSize();
1007 }
1008
1009 std::shared_ptr<FilterContents> blur;
1010 switch (selected_pass_variation) {
1011 case 0:
1012 blur = std::make_shared<GaussianBlurFilterContents>(
1013 blur_sigma_x.sigma, blur_sigma_y.sigma,
1014 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1015 /*geometry=*/nullptr);
1016 blur->SetInputs({FilterInput::Make(input)});
1017 break;
1018 case 1:
1019 blur = FilterContents::MakeGaussianBlur(
1020 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1021 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1022 break;
1023 };
1024 FML_CHECK(blur);
1025
1026 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1027 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1028 blur_styles[selected_blur_style]);
1029
1030 auto ctm = Matrix::MakeScale(GetContentScale()) *
1031 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1032 Matrix::MakeRotationZ(Radians(rotation)) *
1033 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1034 Matrix::MakeSkew(skew[0], skew[1]) *
1035 Matrix::MakeTranslation(-Point(input_size) / 2);
1036
1037 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1038
1039 Entity entity;
1040 entity.SetContents(target_contents);
1041 entity.SetTransform(ctm);
1042
1043 entity.Render(context, pass);
1044
1045 // Renders a red "cover" rectangle that shows the original position of the
1046 // unfiltered input.
1047 Entity cover_entity;
1048 static std::unique_ptr<Geometry> geom =
1049 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1050 auto contents = std::make_shared<SolidColorContents>();
1051 contents->SetColor(cover_color);
1052 contents->SetGeometry(geom.get());
1053 cover_entity.SetContents(std::move(contents));
1054 cover_entity.SetTransform(ctm);
1055 cover_entity.Render(context, pass);
1056
1057 // Renders a green bounding rect of the target filter.
1058 Entity bounds_entity;
1059 std::optional<Rect> target_contents_coverage =
1060 target_contents->GetCoverage(entity);
1061 if (target_contents_coverage.has_value()) {
1062 static std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
1063 PathBuilder{}
1064 .AddRect(target_contents->GetCoverage(entity).value())
1065 .TakePath());
1066 auto contents = std::make_shared<SolidColorContents>();
1067 contents->SetColor(bounds_color);
1068 contents->SetGeometry(geom.get());
1069
1070 bounds_entity.SetContents(contents);
1071 bounds_entity.SetTransform(Matrix());
1072 bounds_entity.Render(context, pass);
1073 }
1074
1075 return true;
1076 };
1077 ASSERT_TRUE(OpenPlaygroundHere(callback));
1078 }

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::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() [345/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 98 of file entity_unittests.cc.

98 {
99 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
100 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
101
102 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
103 Rect::MakeXYWH(200, 200, 200, 200));
104 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST_P() [346/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2075 of file entity_unittests.cc.

2075 {
2076 Matrix matrix;
2077 LinearGradientContents contents;
2078 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2079 contents.SetGeometry(geom.get());
2080
2081 contents.SetColors({Color::CornflowerBlue()});
2082 EXPECT_TRUE(contents.IsOpaque(matrix));
2083 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2084 EXPECT_FALSE(contents.IsOpaque(matrix));
2085 contents.SetColors({Color::CornflowerBlue()});
2086 contents.SetTileMode(Entity::TileMode::kDecal);
2087 EXPECT_FALSE(contents.IsOpaque(matrix));
2088
2089 // Create stroked path that required alpha coverage.
2090 geom = Geometry::MakeStrokePath(
2091 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2092 /*stroke_width=*/0.05);
2093 contents.SetGeometry(geom.get());
2094 contents.SetColors({Color::CornflowerBlue()});
2095
2096 EXPECT_FALSE(contents.IsOpaque(matrix));
2097 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::LinearGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::LinearGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), impeller::LinearGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [347/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1558 of file entity_unittests.cc.

1558 {
1559 auto image = CreateTextureForFixture("kalimba.jpg");
1560 ASSERT_TRUE(image);
1561
1562 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1563 auto filtered =
1564 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1565
1566 // Define the entity that will serve as the control image as a Gaussian blur
1567 // filter with no filter at all.
1568 Entity entity_left;
1569 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1570 Matrix::MakeTranslation({100, 300}) *
1571 Matrix::MakeScale(Vector2{0.5, 0.5}));
1572 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1573 Sigma{0}, Sigma{0});
1574 entity_left.SetContents(unfiltered);
1575
1576 // Define the entity that will be filtered from linear to sRGB.
1577 Entity entity_right;
1578 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1579 Matrix::MakeTranslation({500, 300}) *
1580 Matrix::MakeScale(Vector2{0.5, 0.5}));
1581 entity_right.SetContents(filtered);
1582 return entity_left.Render(context, pass) &&
1583 entity_right.Render(context, pass);
1584 };
1585
1586 ASSERT_TRUE(OpenPlaygroundHere(callback));
1587 }

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() [348/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1536 of file entity_unittests.cc.

1536 {
1537 // Set up a simple color background.
1538 auto geom = Geometry::MakeFillPath(
1539 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1540 auto fill = std::make_shared<SolidColorContents>();
1541 fill->SetGeometry(geom.get());
1542 fill->SetColor(Color::MintCream());
1543
1544 auto filter =
1545 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1546
1547 Entity e;
1548 e.SetTransform(Matrix());
1549
1550 // Confirm that the actual filter coverage matches the expected coverage.
1551 auto actual = filter->GetCoverage(e);
1552 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1553
1554 ASSERT_TRUE(actual.has_value());
1555 ASSERT_RECT_NEAR(actual.value(), expected);
1556 }

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() [349/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1080 of file entity_unittests.cc.

1080 {
1081 auto boston = CreateTextureForFixture("boston.jpg");
1082 ASSERT_TRUE(boston);
1083
1084 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1085 const char* morphology_type_names[] = {"Dilate", "Erode"};
1086 const FilterContents::MorphType morphology_types[] = {
1087 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1088 static Color input_color = Color::Black();
1089 // UI state.
1090 static int selected_morphology_type = 0;
1091 static float radius[2] = {20, 20};
1092 static Color cover_color(1, 0, 0, 0.2);
1093 static Color bounds_color(0, 1, 0, 0.1);
1094 static float offset[2] = {500, 400};
1095 static float rotation = 0;
1096 static float scale[2] = {0.65, 0.65};
1097 static float skew[2] = {0, 0};
1098 static float path_rect[4] = {0, 0,
1099 static_cast<float>(boston->GetSize().width),
1100 static_cast<float>(boston->GetSize().height)};
1101 static float effect_transform_scale = 1;
1102
1103 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1104 {
1105 ImGui::Combo("Morphology type", &selected_morphology_type,
1106 morphology_type_names,
1107 sizeof(morphology_type_names) / sizeof(char*));
1108 ImGui::SliderFloat2("Radius", radius, 0, 200);
1109 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1110 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1111 ImGui::ColorEdit4("Bounds color ",
1112 reinterpret_cast<float*>(&bounds_color));
1113 ImGui::SliderFloat2("Translation", offset, 0,
1114 pass.GetRenderTargetSize().width);
1115 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1116 ImGui::SliderFloat2("Scale", scale, 0, 3);
1117 ImGui::SliderFloat2("Skew", skew, -3, 3);
1118 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1119 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1120 3);
1121 }
1122 ImGui::End();
1123
1124 std::shared_ptr<Contents> input;
1125 Size input_size;
1126
1127 auto input_rect =
1128 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1129 auto texture = std::make_shared<TextureContents>();
1130 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1131 texture->SetDestinationRect(input_rect);
1132 texture->SetTexture(boston);
1133 texture->SetOpacity(input_color.alpha);
1134
1135 input = texture;
1136 input_size = input_rect.GetSize();
1137
1138 auto contents = FilterContents::MakeMorphology(
1139 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1140 morphology_types[selected_morphology_type]);
1141 contents->SetEffectTransform(Matrix::MakeScale(
1142 Vector2{effect_transform_scale, effect_transform_scale}));
1143
1144 auto ctm = Matrix::MakeScale(GetContentScale()) *
1145 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1146 Matrix::MakeRotationZ(Radians(rotation)) *
1147 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1148 Matrix::MakeSkew(skew[0], skew[1]) *
1149 Matrix::MakeTranslation(-Point(input_size) / 2);
1150
1151 Entity entity;
1152 entity.SetContents(contents);
1153 entity.SetTransform(ctm);
1154
1155 entity.Render(context, pass);
1156
1157 // Renders a red "cover" rectangle that shows the original position of the
1158 // unfiltered input.
1159 Entity cover_entity;
1160 static std::unique_ptr<Geometry> geom =
1161 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1162 auto cover_contents = std::make_shared<SolidColorContents>();
1163 cover_contents->SetColor(cover_color);
1164 cover_contents->SetGeometry(geom.get());
1165 cover_entity.SetContents(cover_contents);
1166 cover_entity.SetTransform(ctm);
1167 cover_entity.Render(context, pass);
1168
1169 // Renders a green bounding rect of the target filter.
1170 Entity bounds_entity;
1171 static std::unique_ptr<Geometry> bounds_geom = Geometry::MakeFillPath(
1172 PathBuilder{}
1173 .AddRect(contents->GetCoverage(entity).value())
1174 .TakePath());
1175 auto bounds_contents = std::make_shared<SolidColorContents>();
1176 bounds_contents->SetColor(bounds_color);
1177 bounds_contents->SetGeometry(bounds_geom.get());
1178 bounds_entity.SetContents(std::move(bounds_contents));
1179 bounds_entity.SetTransform(Matrix());
1180
1181 bounds_entity.Render(context, pass);
1182
1183 return true;
1184 };
1185 ASSERT_TRUE(OpenPlaygroundHere(callback));
1186 }

References impeller::PathBuilder::AddRect(), impeller::Color::alpha, impeller::Color::Black(), impeller::FilterContents::kDilate, impeller::FilterContents::kErode, impeller::kPi, impeller::FilterInput::Make(), impeller::Geometry::MakeFillPath(), 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() [350/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2158 of file entity_unittests.cc.

2158 {
2159 std::vector<Point> points = {{10, 20}, {100, 200}};
2160 auto geometry = Geometry::MakePointField(points, 5.0, false);
2161 ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2162 ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2163 Rect::MakeLTRB(35, 15, 135, 205));
2164 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakePointField(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [351/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2099 of file entity_unittests.cc.

2099 {
2100 Matrix matrix;
2101 RadialGradientContents contents;
2102 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2103 contents.SetGeometry(geom.get());
2104
2105 contents.SetColors({Color::CornflowerBlue()});
2106 EXPECT_TRUE(contents.IsOpaque(matrix));
2107 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2108 EXPECT_FALSE(contents.IsOpaque(matrix));
2109 contents.SetColors({Color::CornflowerBlue()});
2110 contents.SetTileMode(Entity::TileMode::kDecal);
2111 EXPECT_FALSE(contents.IsOpaque(matrix));
2112
2113 // Create stroked path that required alpha coverage.
2114 geom = Geometry::MakeStrokePath(
2115 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2116 /*stroke_width=*/0.05);
2117 contents.SetGeometry(geom.get());
2118 contents.SetColors({Color::CornflowerBlue()});
2119
2120 EXPECT_FALSE(contents.IsOpaque(matrix));
2121 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::RadialGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [352/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1394 of file entity_unittests.cc.

1394 {
1395 auto callback = [&](ContentContext& context, RenderPass& pass) {
1396 static Color color = Color::Red();
1397 static float corner_radius = 100;
1398 static float blur_radius = 100;
1399 static bool show_coverage = false;
1400 static Color coverage_color = Color::Green().WithAlpha(0.2);
1401
1402 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1403 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1404 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1405 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1406 ImGui::Checkbox("Show coverage", &show_coverage);
1407 if (show_coverage) {
1408 ImGui::ColorEdit4("Coverage color",
1409 reinterpret_cast<Scalar*>(&coverage_color));
1410 }
1411 ImGui::End();
1412
1413 static PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1414 static PlaygroundPoint bottom_right_point(Point(600, 400), 30,
1415 Color::White());
1416 auto [top_left, bottom_right] =
1417 DrawPlaygroundLine(top_left_point, bottom_right_point);
1418 auto rect =
1419 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1420
1421 auto contents = std::make_unique<SolidRRectBlurContents>();
1422 contents->SetRRect(rect, {corner_radius, corner_radius});
1423 contents->SetColor(color);
1424 contents->SetSigma(Radius(blur_radius));
1425
1426 Entity entity;
1427 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1428 entity.SetContents(std::move(contents));
1429 entity.Render(context, pass);
1430
1431 auto coverage = entity.GetCoverage();
1432 if (show_coverage && coverage.has_value()) {
1433 auto bounds_contents = std::make_unique<SolidColorContents>();
1434 auto geom = Geometry::MakeFillPath(
1435 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
1436 bounds_contents->SetGeometry(geom.get());
1437 bounds_contents->SetColor(coverage_color.Premultiply());
1438 Entity bounds_entity;
1439 bounds_entity.SetContents(std::move(bounds_contents));
1440 bounds_entity.Render(context, pass);
1441 }
1442
1443 return true;
1444 };
1445 ASSERT_TRUE(OpenPlaygroundHere(callback));
1446 }

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() [353/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 1754 of file entity_unittests.cc.

1754 {
1755 auto runtime_stages =
1756 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1757 auto runtime_stage =
1758 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1759 ASSERT_TRUE(runtime_stage);
1760 ASSERT_TRUE(runtime_stage->IsDirty());
1761
1762 bool expect_dirty = true;
1763 Pipeline<PipelineDescriptor>* first_pipeline;
1764 static std::unique_ptr<Geometry> geom = Geometry::MakeCover();
1765
1766 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1767 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1768
1769 auto contents = std::make_shared<RuntimeEffectContents>();
1770 contents->SetGeometry(geom.get());
1771 contents->SetRuntimeStage(runtime_stage);
1772
1773 struct FragUniforms {
1774 Vector2 iResolution;
1775 Scalar iTime;
1776 } frag_uniforms = {
1777 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1778 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1779 };
1780 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1781 uniform_data->resize(sizeof(FragUniforms));
1782 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1783 contents->SetUniformData(uniform_data);
1784
1785 Entity entity;
1786 entity.SetContents(contents);
1787 bool result = contents->Render(context, entity, pass);
1788
1789 if (expect_dirty) {
1790 EXPECT_NE(first_pipeline, pass.GetCommands().back().pipeline.get());
1791 first_pipeline = pass.GetCommands().back().pipeline.get();
1792 } else {
1793 EXPECT_EQ(pass.GetCommands().back().pipeline.get(), first_pipeline);
1794 }
1795
1796 expect_dirty = false;
1797 return result;
1798 };
1799
1800 // Simulate some renders and hot reloading of the shader.
1801 auto content_context = GetContentContext();
1802 {
1803 RenderTarget target =
1804 content_context->GetRenderTargetCache()->CreateOffscreen(
1805 *content_context->GetContext(), {1, 1}, 1u);
1806
1807 testing::MockRenderPass mock_pass(GetContext(), target);
1808 callback(*content_context, mock_pass);
1809 callback(*content_context, mock_pass);
1810
1811 // Dirty the runtime stage.
1812 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1813 runtime_stage =
1814 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1815
1816 ASSERT_TRUE(runtime_stage->IsDirty());
1817 expect_dirty = true;
1818
1819 callback(*content_context, mock_pass);
1820 }
1821 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [354/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanPrecache |
| ) |  |

Definition at line 1870 of file entity_unittests.cc.

1870 {
1871 auto runtime_stages =
1872 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1873 auto runtime_stage =
1874 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1875 ASSERT_TRUE(runtime_stage);
1876 ASSERT_TRUE(runtime_stage->IsDirty());
1877
1878 auto contents = std::make_shared<RuntimeEffectContents>();
1879 contents->SetRuntimeStage(runtime_stage);
1880
1881 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
1882 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [355/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 1823 of file entity_unittests.cc.

1823 {
1824 auto runtime_stages =
1825 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1826 auto runtime_stage =
1827 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1828 ASSERT_TRUE(runtime_stage);
1829 ASSERT_TRUE(runtime_stage->IsDirty());
1830
1831 auto contents = std::make_shared<RuntimeEffectContents>();
1832 auto geom = Geometry::MakeCover();
1833 contents->SetGeometry(geom.get());
1834 contents->SetRuntimeStage(runtime_stage);
1835
1836 struct FragUniforms {
1837 Vector2 iResolution;
1838 Scalar iTime;
1839 } frag_uniforms = {
1840 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1841 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1842 };
1843 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1844 uniform_data->resize(sizeof(FragUniforms));
1845 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1846 contents->SetUniformData(uniform_data);
1847
1848 Entity entity;
1849 entity.SetContents(contents);
1850
1851 // Create a render target with a depth-stencil, similar to how EntityPass
1852 // does.
1853 RenderTarget target =
1854 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
1855 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
1856 "RuntimeEffect Texture");
1857 testing::MockRenderPass pass(GetContext(), target);
1858
1859 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
1860 ASSERT_EQ(pass.GetCommands().size(), 1u);
1861 const auto& command = pass.GetCommands()[0];
1862 ASSERT_TRUE(command.pipeline->GetDescriptor()
1863 .GetDepthStencilAttachmentDescriptor()
1864 .has_value());
1865 ASSERT_TRUE(command.pipeline->GetDescriptor()
1866 .GetFrontStencilAttachmentDescriptor()
1867 .has_value());
1868 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [356/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 1884 of file entity_unittests.cc.

1884 {
1885 if (GetBackend() != PlaygroundBackend::kVulkan) {
1886 GTEST_SKIP() << "Test only applies to Vulkan";
1887 }
1888
1889 auto runtime_stages =
1890 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1891 auto runtime_stage =
1892 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1893 ASSERT_TRUE(runtime_stage);
1894 ASSERT_TRUE(runtime_stage->IsDirty());
1895
1896 auto contents = std::make_shared<RuntimeEffectContents>();
1897 auto geom = Geometry::MakeCover();
1898 contents->SetGeometry(geom.get());
1899 contents->SetRuntimeStage(runtime_stage);
1900
1901 struct FragUniforms {
1902 Vector2 iResolution;
1903 Scalar iTime;
1904 } frag_uniforms = {
1905 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1906 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1907 };
1908 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1909 uniform_data->resize(sizeof(FragUniforms));
1910 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1911 contents->SetUniformData(uniform_data);
1912
1913 Entity entity;
1914 entity.SetContents(contents);
1915
1916 auto context = GetContentContext();
1917 RenderTarget target = context->GetRenderTargetCache()->CreateOffscreen(
1918 *context->GetContext(), {1, 1}, 1u);
1919
1920 testing::MockRenderPass pass(GetContext(), target);
1921 ASSERT_TRUE(contents->Render(*context, entity, pass));
1922 ASSERT_EQ(pass.GetCommands().size(), 1u);
1923 const auto& command = pass.GetCommands()[0];
1924 ASSERT_EQ(command.fragment_bindings.buffers.size(), 1u);
1925 // 16 bytes:
1926 // 8 bytes for iResolution
1927 // 4 bytes for iTime
1928 // 4 bytes padding
1929 EXPECT_EQ(command.fragment_bindings.buffers[0].view.resource.range.length,
1930 16u);
1931 }

References impeller::kVulkan, impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [357/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1188 of file entity_unittests.cc.

1188 {
1189 Entity entity;
1190 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSourceOver);
1191 entity.SetBlendMode(BlendMode::kClear);
1192 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1193 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSourceOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [358/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorApplyColorFilter |
| ) |  |

Definition at line 2399 of file entity_unittests.cc.

2399 {
2400 auto contents = SolidColorContents();
2401 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2402 auto result = contents.ApplyColorFilter([](const Color& color) {
2403 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2404 });
2405 ASSERT_TRUE(result);
2406 ASSERT_COLOR_NEAR(contents.GetColor(),
2407 Color(0.424452, 0.828743, 0.79105, 0.9375));
2408 }

References ASSERT_COLOR_NEAR, color, impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [359/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2033 of file entity_unittests.cc.

2033 {
2034 Matrix matrix;
2035 SolidColorContents contents;
2036 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2037 contents.SetGeometry(geom.get());
2038
2039 contents.SetColor(Color::CornflowerBlue());
2040 EXPECT_TRUE(contents.IsOpaque(matrix));
2041 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2042 EXPECT_FALSE(contents.IsOpaque(matrix));
2043
2044 // Create stroked path that required alpha coverage.
2045 geom = Geometry::MakeStrokePath(
2046 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2047 /*stroke_width=*/0.05);
2048 contents.SetGeometry(geom.get());
2049 contents.SetColor(Color::CornflowerBlue());
2050
2051 EXPECT_FALSE(contents.IsOpaque(matrix));
2052 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::SolidColorContents::IsOpaque(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::SolidColorContents::SetColor(), and impeller::ColorSourceContents::SetGeometry().

## ◆ TEST_P() [360/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 677 of file entity_unittests.cc.

677 {
678 {
679 auto geometry = Geometry::MakeStrokePath(Path{});
680 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
681 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
682 }
683
684 {
685 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0,
686 /*miter_limit=*/8.0);
687 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
688 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
689 }
690
691 {
692 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0,
693 /*miter_limit=*/-1.0);
694 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
695 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
696 }
697 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [361/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 655 of file entity_unittests.cc.

655 {
656 {
657 auto geometry = Geometry::MakeStrokePath(Path{});
658 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
659 // Defaults.
660 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
661 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
662 }
663
664 {
665 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
666 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
667 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
668 }
669
670 {
671 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
672 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
673 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
674 }
675 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [362/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1285 of file entity_unittests.cc.

1285 {
1286 // No transform
1287 {
1288 auto fill = std::make_shared<SolidColorContents>();
1289 fill->SetColor(Color::CornflowerBlue());
1290 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1291 auto geom =
1292 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath());
1293 fill->SetGeometry(geom.get());
1294
1295 auto coverage = fill->GetCoverage({});
1296 ASSERT_TRUE(coverage.has_value());
1297 ASSERT_RECT_NEAR(coverage.value(), expected);
1298 }
1299
1300 // Entity transform
1301 {
1302 auto fill = std::make_shared<SolidColorContents>();
1303 auto geom = Geometry::MakeFillPath(
1304 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
1305 fill->SetColor(Color::CornflowerBlue());
1306 fill->SetGeometry(geom.get());
1307
1308 Entity entity;
1309 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1310 entity.SetContents(std::move(fill));
1311
1312 auto coverage = entity.GetCoverage();
1313 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1314 ASSERT_TRUE(coverage.has_value());
1315 ASSERT_RECT_NEAR(coverage.value(), expected);
1316 }
1317
1318 // No coverage for fully transparent colors
1319 {
1320 auto fill = std::make_shared<SolidColorContents>();
1321 auto geom = Geometry::MakeFillPath(
1322 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
1323 fill->SetColor(Color::WhiteTransparent());
1324 fill->SetGeometry(geom.get());
1325
1326 auto coverage = fill->GetCoverage({});
1327 ASSERT_FALSE(coverage.has_value());
1328 }
1329 }

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() [363/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1201 of file entity_unittests.cc.

1201 {
1202 {
1203 auto geometry = Geometry::MakeStrokePath(
1204 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1205 Cap::kButt, Join::kBevel);
1206
1207 Entity entity;
1208 auto contents = std::make_unique<SolidColorContents>();
1209 contents->SetGeometry(geometry.get());
1210 contents->SetColor(Color::Black());
1211 entity.SetContents(std::move(contents));
1212 auto actual = entity.GetCoverage();
1213 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1214
1215 ASSERT_TRUE(actual.has_value());
1216 ASSERT_RECT_NEAR(actual.value(), expected);
1217 }
1218
1219 // Cover the Cap::kSquare case.
1220 {
1221 auto geometry = Geometry::MakeStrokePath(
1222 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1223 Cap::kSquare, Join::kBevel);
1224
1225 Entity entity;
1226 auto contents = std::make_unique<SolidColorContents>();
1227 contents->SetGeometry(geometry.get());
1228 contents->SetColor(Color::Black());
1229 entity.SetContents(std::move(contents));
1230 auto actual = entity.GetCoverage();
1231 auto expected =
1232 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1233
1234 ASSERT_TRUE(actual.has_value());
1235 ASSERT_RECT_NEAR(actual.value(), expected);
1236 }
1237
1238 // Cover the Join::kMiter case.
1239 {
1240 auto geometry = Geometry::MakeStrokePath(
1241 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1242 Cap::kSquare, Join::kMiter);
1243
1244 Entity entity;
1245 auto contents = std::make_unique<SolidColorContents>();
1246 contents->SetGeometry(geometry.get());
1247 contents->SetColor(Color::Black());
1248 entity.SetContents(std::move(contents));
1249 auto actual = entity.GetCoverage();
1250 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1251
1252 ASSERT_TRUE(actual.has_value());
1253 ASSERT_RECT_NEAR(actual.value(), expected);
1254 }
1255 }

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() [364/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2194 of file entity_unittests.cc.

2194 {
2195 auto content_context = GetContentContext();
2196
2197 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2198 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2199 .has_depth_stencil_attachments = false,
2200 });
2201 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2202 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2203 .has_depth_stencil_attachments = true});
2204
2205 EXPECT_NE(default_gyph, alt_gyph);
2206 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2207 alt_gyph->GetDescriptor().GetSpecializationConstants());
2208
2209 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2210 PixelFormat::kA8UNormInt;
2211
2212 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2213 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2214 expected_constants);
2215 }

References impeller::kA8UNormInt, and impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [365/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1611 of file entity_unittests.cc.

1611 {
1612 auto image = CreateTextureForFixture("embarcadero.jpg");
1613 ASSERT_TRUE(image);
1614
1615 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1616 auto filtered =
1617 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1618
1619 // Define the entity that will serve as the control image as a Gaussian blur
1620 // filter with no filter at all.
1621 Entity entity_left;
1622 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1623 Matrix::MakeTranslation({100, 300}) *
1624 Matrix::MakeScale(Vector2{0.5, 0.5}));
1625 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1626 Sigma{0}, Sigma{0});
1627 entity_left.SetContents(unfiltered);
1628
1629 // Define the entity that will be filtered from sRGB to linear.
1630 Entity entity_right;
1631 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1632 Matrix::MakeTranslation({500, 300}) *
1633 Matrix::MakeScale(Vector2{0.5, 0.5}));
1634 entity_right.SetContents(filtered);
1635 return entity_left.Render(context, pass) &&
1636 entity_right.Render(context, pass);
1637 };
1638
1639 ASSERT_TRUE(OpenPlaygroundHere(callback));
1640 }

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() [366/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1589 of file entity_unittests.cc.

1589 {
1590 // Set up a simple color background.
1591 auto fill = std::make_shared<SolidColorContents>();
1592 auto geom = Geometry::MakeFillPath(
1593 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1594 fill->SetGeometry(geom.get());
1595 fill->SetColor(Color::DeepPink());
1596
1597 auto filter =
1598 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1599
1600 Entity e;
1601 e.SetTransform(Matrix());
1602
1603 // Confirm that the actual filter coverage matches the expected coverage.
1604 auto actual = filter->GetCoverage(e);
1605 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1606
1607 ASSERT_TRUE(actual.has_value());
1608 ASSERT_RECT_NEAR(actual.value(), expected);
1609 }

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() [367/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 194 of file entity_unittests.cc.

194 {
195 const Point padding(300, 250);
196 const Point margin(140, 180);
197
198 auto callback = [&](ContentContext& context, RenderPass& pass) {
199 // Slightly above sqrt(2) by default, so that right angles are just below
200 // the limit and acute angles are over the limit (causing them to get
201 // beveled).
202 static Scalar miter_limit = 1.41421357;
203 static Scalar width = 30;
204
205 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
206 {
207 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
208 ImGui::SliderFloat("Stroke width", &width, 0, 100);
209 if (ImGui::Button("Reset")) {
210 miter_limit = 1.41421357;
211 width = 30;
212 }
213 }
214 ImGui::End();
215
216 auto world_matrix = Matrix::MakeScale(GetContentScale());
217 auto render_path = [width = width, &context, &pass, &world_matrix](
218 const Path& path, Cap cap, Join join) {
219 auto contents = std::make_unique<SolidColorContents>();
220 static std::unique_ptr<Geometry> geom =
221 Geometry::MakeStrokePath(path, width, miter_limit, cap, join);
222 contents->SetGeometry(geom.get());
223 contents->SetColor(Color::Red());
224
225 Entity entity;
226 entity.SetTransform(world_matrix);
227 entity.SetContents(std::move(contents));
228
229 auto coverage = entity.GetCoverage();
230 if (coverage.has_value()) {
231 auto bounds_contents = std::make_unique<SolidColorContents>();
232
233 static std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
234 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
235
236 bounds_contents->SetGeometry(geom.get());
237 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
238 Entity bounds_entity;
239 bounds_entity.SetContents(std::move(bounds_contents));
240 bounds_entity.Render(context, pass);
241 }
242
243 entity.Render(context, pass);
244 };
245
246 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
247 e_def(75, 75);
248 const Scalar r = 30;
249 // Cap::kButt demo.
250 {
251 Point off = Point(0, 0) * padding + margin;
252 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
253 static PlaygroundPoint point_b(off + b_def, r, Color::White());
254 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
255 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
256 static PlaygroundPoint point_d(off + d_def, r, Color::White());
257 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
258 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
259 Cap::kButt, Join::kBevel);
260 }
261
262 // Cap::kSquare demo.
263 {
264 Point off = Point(1, 0) * padding + margin;
265 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
266 static PlaygroundPoint point_b(off + b_def, r, Color::White());
267 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
268 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
269 static PlaygroundPoint point_d(off + d_def, r, Color::White());
270 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
271 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
272 Cap::kSquare, Join::kBevel);
273 }
274
275 // Cap::kRound demo.
276 {
277 Point off = Point(2, 0) * padding + margin;
278 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
279 static PlaygroundPoint point_b(off + b_def, r, Color::White());
280 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
281 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
282 static PlaygroundPoint point_d(off + d_def, r, Color::White());
283 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
284 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
285 Cap::kRound, Join::kBevel);
286 }
287
288 // Join::kBevel demo.
289 {
290 Point off = Point(0, 1) * padding + margin;
291 static PlaygroundPoint point_a =
292 PlaygroundPoint(off + a_def, r, Color::White());
293 static PlaygroundPoint point_b =
294 PlaygroundPoint(off + e_def, r, Color::White());
295 static PlaygroundPoint point_c =
296 PlaygroundPoint(off + c_def, r, Color::White());
297 Point a = DrawPlaygroundPoint(point_a);
298 Point b = DrawPlaygroundPoint(point_b);
299 Point c = DrawPlaygroundPoint(point_c);
300 render_path(
301 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
302 Cap::kButt, Join::kBevel);
303 }
304
305 // Join::kMiter demo.
306 {
307 Point off = Point(1, 1) * padding + margin;
308 static PlaygroundPoint point_a(off + a_def, r, Color::White());
309 static PlaygroundPoint point_b(off + e_def, r, Color::White());
310 static PlaygroundPoint point_c(off + c_def, r, Color::White());
311 Point a = DrawPlaygroundPoint(point_a);
312 Point b = DrawPlaygroundPoint(point_b);
313 Point c = DrawPlaygroundPoint(point_c);
314 render_path(
315 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
316 Cap::kButt, Join::kMiter);
317 }
318
319 // Join::kRound demo.
320 {
321 Point off = Point(2, 1) * padding + margin;
322 static PlaygroundPoint point_a(off + a_def, r, Color::White());
323 static PlaygroundPoint point_b(off + e_def, r, Color::White());
324 static PlaygroundPoint point_c(off + c_def, r, Color::White());
325 Point a = DrawPlaygroundPoint(point_a);
326 Point b = DrawPlaygroundPoint(point_b);
327 Point c = DrawPlaygroundPoint(point_c);
328 render_path(
329 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
330 Cap::kButt, Join::kRound);
331 }
332
333 return true;
334 };
335 ASSERT_TRUE(OpenPlaygroundHere(callback));
336 }

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() [368/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 127 of file entity_unittests.cc.

127 {
128 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
129 Path path = PathBuilder{}
130 .MoveTo({100, 100})
131 .LineTo({100, 200})
132 .MoveTo({100, 300})
133 .LineTo({100, 400})
134 .MoveTo({100, 500})
135 .LineTo({100, 600})
136 .TakePath();
137
138 Entity entity;
139 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
140 auto contents = std::make_unique<TiledTextureContents>();
141 static std::unique_ptr<Geometry> geom = Geometry::MakeStrokePath(path, 100.0);
142 contents->SetGeometry(geom.get());
143 contents->SetTexture(bridge);
144 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
145 entity.SetContents(std::move(contents));
146 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
147 }

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() [369/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2123 of file entity_unittests.cc.

2123 {
2124 Matrix matrix;
2125 RadialGradientContents contents;
2126 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2127 contents.SetGeometry(geom.get());
2128
2129 contents.SetColors({Color::CornflowerBlue()});
2130 EXPECT_TRUE(contents.IsOpaque(matrix));
2131 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2132 EXPECT_FALSE(contents.IsOpaque(matrix));
2133 contents.SetColors({Color::CornflowerBlue()});
2134 contents.SetTileMode(Entity::TileMode::kDecal);
2135 EXPECT_FALSE(contents.IsOpaque(matrix));
2136
2137 // Create stroked path that required alpha coverage.
2138 geom = Geometry::MakeStrokePath(
2139 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2140 /*stroke_width=*/0.05);
2141 contents.SetGeometry(geom.get());
2142 contents.SetColors({Color::CornflowerBlue()});
2143
2144 EXPECT_FALSE(contents.IsOpaque(matrix));
2145 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::RadialGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [370/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2186 of file entity_unittests.cc.

2186 {
2187 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f, 12), 0.43f);
2188 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f, 12), 0.53f);
2189 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f, 12), 2.1f);
2190 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
2191 ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f, 12), 48.0f);
2192 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [371/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 106 of file entity_unittests.cc.

106 {
107 Path path = PathBuilder{}
108 .MoveTo({100, 100})
109 .LineTo({100, 200})
110 .MoveTo({100, 300})
111 .LineTo({100, 400})
112 .MoveTo({100, 500})
113 .LineTo({100, 600})
114 .TakePath();
115
116 Entity entity;
117 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
118 auto contents = std::make_unique<SolidColorContents>();
119
120 static std::unique_ptr<Geometry> geom = Geometry::MakeStrokePath(path, 5.0);
121 contents->SetGeometry(geom.get());
122 contents->SetColor(Color::Red());
123 entity.SetContents(std::move(contents));
124 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
125 }

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() [372/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2147 of file entity_unittests.cc.

2147 {
2148 Matrix matrix;
2149 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2150 TiledTextureContents contents;
2151 contents.SetTexture(bay_bridge);
2152 // This is a placeholder test. Images currently never decompress as opaque
2153 // (whether in Flutter or the playground), and so this should currently always
2154 // return false in practice.
2155 EXPECT_FALSE(contents.IsOpaque(matrix));
2156 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [373/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipeline |
| ) |  |

Definition at line 21 of file tiled_texture_contents_unittests.cc.

21 {
22 TextureDescriptor texture_desc;
23 texture_desc.size = {100, 100};
24 texture_desc.type = TextureType::kTexture2D;
25 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
26 texture_desc.storage_mode = StorageMode::kDevicePrivate;
27 auto texture =
28 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
29
30 auto geom = Geometry::MakeCover();
31 TiledTextureContents contents;
32 contents.SetTexture(texture);
33 contents.SetGeometry(geom.get());
34
35 auto content_context = GetContentContext();
36 auto buffer = content_context->GetContext()->CreateCommandBuffer();
37 auto render_target =
38 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
39 *content_context->GetContext(), {100, 100},
40 /*mip_count=*/1);
41 auto render_pass = buffer->CreateRenderPass(render_target);
42 auto recording_pass = std::make_shared<RecordingRenderPass>(
43 render_pass, GetContext(), render_target);
44
45 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *recording_pass));
46 const std::vector<Command>& commands = recording_pass->GetCommands();
47
48 ASSERT_EQ(commands.size(), 1u);
49 #ifdef IMPELLER_DEBUG
50 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
51 "TextureFill Pipeline") != std::string::npos);
52 #endif // IMPELLER_DEBUG
53 auto options = OptionsFromPassAndEntity(*recording_pass, {});
54 options.primitive_type = PrimitiveType::kTriangleStrip;
55 EXPECT_EQ(commands[0].pipeline,
56 GetContentContext()->GetTiledTexturePipeline(options));
57
58 if (GetParam() == PlaygroundBackend::kMetal) {
59 recording_pass->EncodeCommands();
60 }
61 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kMetal, impeller::kR8G8B8A8UNormInt, impeller::kTexture2D, impeller::kTriangleStrip, impeller::Geometry::MakeCover(), impeller::OptionsFromPassAndEntity(), impeller::ContentContextOptions::primitive_type, impeller::TiledTextureContents::Render(), impeller::ColorSourceContents::SetGeometry(), impeller::TiledTextureContents::SetTexture(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [374/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipelineExternalOES |
| ) |  |

Definition at line 65 of file tiled_texture_contents_unittests.cc.

65 {
66 if (GetParam() != PlaygroundBackend::kOpenGLES) {
67 GTEST_SKIP()
68 << "External OES textures are only valid for the OpenGLES backend.";
69 }
70
71 TextureDescriptor texture_desc;
72 texture_desc.size = {100, 100};
73 texture_desc.type = TextureType::kTextureExternalOES;
74 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
75 texture_desc.storage_mode = StorageMode::kDevicePrivate;
76 auto texture =
77 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
78 auto contents = TextureContents::MakeRect(Rect::MakeSize(texture->GetSize()));
79 contents->SetTexture(texture);
80 contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
81 contents->SetStrictSourceRect(false);
82
83 auto content_context = GetContentContext();
84 auto buffer = content_context->GetContext()->CreateCommandBuffer();
85 auto render_target =
86 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
87 *content_context->GetContext(), {100, 100},
88 /*mip_count=*/1);
89 auto render_pass = buffer->CreateRenderPass(render_target);
90
91 ASSERT_TRUE(contents->Render(*GetContentContext(), {}, *render_pass));
92 const std::vector<Command>& commands = render_pass->GetCommands();
93
94 ASSERT_EQ(commands.size(), 1u);
95
96 auto options = OptionsFromPassAndEntity(*render_pass, {});
97 options.primitive_type = PrimitiveType::kTriangleStrip;
98 EXPECT_EQ(commands[0].pipeline,
99 GetContentContext()->GetTiledTextureExternalPipeline(options));
100 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kTextureExternalOES, impeller::kTriangleStrip, impeller::TextureContents::MakeRect(), impeller::TRect< Scalar >::MakeSize(), impeller::OptionsFromPassAndEntity(), impeller::ContentContextOptions::primitive_type, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [375/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 149 of file entity_unittests.cc.

149 {
150 auto callback = [&](ContentContext& context, RenderPass& pass) {
151 Point offset(100, 100);
152
153 static PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
154 Point a = DrawPlaygroundPoint(point_a);
155 static PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
156 Point b = DrawPlaygroundPoint(point_b);
157 static PlaygroundPoint point_c(Point(210, 210) + offset, 20,
158 Color::White());
159 Point c = DrawPlaygroundPoint(point_c);
160 static PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
161 Point d = DrawPlaygroundPoint(point_d);
162 static PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
163 Point e = DrawPlaygroundPoint(point_e);
164 static PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
165 Point f = DrawPlaygroundPoint(point_f);
166 static PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
167 Point g = DrawPlaygroundPoint(point_g);
168 Path path = PathBuilder{}
169 .MoveTo(a)
170 .LineTo(b)
171 .LineTo(c)
172 .LineTo(d)
173 .Close()
174 .MoveTo(e)
175 .LineTo(f)
176 .LineTo(g)
177 .Close()
178 .TakePath();
179
180 Entity entity;
181 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
182 auto contents = std::make_unique<SolidColorContents>();
183 static std::unique_ptr<Geometry> geom =
184 Geometry::MakeStrokePath(path, 20.0);
185 contents->SetGeometry(geom.get());
186 contents->SetColor(Color::Red());
187 entity.SetContents(std::move(contents));
188
189 return entity.Render(context, pass);
190 };
191 ASSERT_TRUE(OpenPlaygroundHere(callback));
192 }

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() [376/454]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 1720 of file entity_unittests.cc.

1720 {
1721 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1722 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
1723 GTEST_SKIP()
1724 << "YUV to RGB filter is not supported on OpenGLES backend yet.";
1725 }
1726
1727 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1728 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
1729 YUVColorSpace::kBT601LimitedRange};
1730 for (int i = 0; i < 2; i++) {
1731 auto yuv_color_space = yuv_color_space_array[i];
1732 auto textures =
1733 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
1734 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
1735 textures[0], textures[1], yuv_color_space);
1736 Entity filter_entity;
1737 filter_entity.SetContents(filter_contents);
1738 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
1739
1740 Entity entity;
1741 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
1742 contents->SetTexture(snapshot->texture);
1743 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
1744 entity.SetContents(contents);
1745 entity.SetTransform(
1746 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
1747 entity.Render(context, pass);
1748 }
1749 return true;
1750 };
1751 ASSERT_TRUE(OpenPlaygroundHere(callback));
1752 }

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() [377/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateUVsSimple |
| ) |  |

Definition at line 334 of file gaussian_blur_filter_contents_unittests.cc.

334 {
335 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
336 auto filter_input = FilterInput::Make(texture);
337 Entity entity;
338 Quad uvs = GaussianBlurFilterContents::CalculateUVs(
339 filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100));
340 std::optional<Rect> uvs_bounds = Rect::MakePointBounds(uvs);
341 EXPECT_TRUE(uvs_bounds.has_value());
342 if (uvs_bounds.has_value()) {
343 EXPECT_TRUE(RectNear(uvs_bounds.value(), Rect::MakeXYWH(0, 0, 1, 1)));
344 }
345 }

References impeller::GaussianBlurFilterContents::CalculateUVs(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakePointBounds(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and uvs.

## ◆ TEST_P() [378/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithEffectTransform |
| ) |  |

Definition at line 186 of file gaussian_blur_filter_contents_unittests.cc.

186 {
187 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
188 fml::StatusOr<Scalar> sigma_radius_1 =
189 CalculateSigmaForBlurRadius(1.0, effect_transform);
190 ASSERT_TRUE(sigma_radius_1.ok());
191 GaussianBlurFilterContents contents(
192 /*sigma_x=*/sigma_radius_1.value(),
193 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
194 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
195 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
196 FilterInput::Vector inputs = {FilterInput::Make(texture)};
197 Entity entity;
198 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
199 std::optional<Rect> coverage =
200 contents.GetFilterCoverage(inputs, entity, effect_transform);
201 EXPECT_TRUE(coverage.has_value());
202 if (coverage.has_value()) {
203 EXPECT_RECT_NEAR(coverage.value(),
204 Rect::MakeLTRB(100 - 1, 100 - 1, 200 + 1, 200 + 1));
205 }
206 }

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() [379/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithTexture |
| ) |  |

Definition at line 165 of file gaussian_blur_filter_contents_unittests.cc.

165 {
166 fml::StatusOr<Scalar> sigma_radius_1 =
167 CalculateSigmaForBlurRadius(1.0, Matrix());
168 ASSERT_TRUE(sigma_radius_1.ok());
169 GaussianBlurFilterContents contents(
170 /*sigma_X=*/sigma_radius_1.value(),
171 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
172 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
173 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
174 FilterInput::Vector inputs = {FilterInput::Make(texture)};
175 Entity entity;
176 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
177 std::optional<Rect> coverage =
178 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
179
180 EXPECT_TRUE(coverage.has_value());
181 if (coverage.has_value()) {
182 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
183 }
184 }

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() [380/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverage |
| ) |  |

Definition at line 238 of file gaussian_blur_filter_contents_unittests.cc.

238 {
239 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
240 fml::StatusOr<Scalar> sigma_radius_1 =
241 CalculateSigmaForBlurRadius(1.0, Matrix());
242 ASSERT_TRUE(sigma_radius_1.ok());
243 auto contents = std::make_unique<GaussianBlurFilterContents>(
244 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
245 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
246 contents->SetInputs({FilterInput::Make(texture)});
247 std::shared_ptr<ContentContext> renderer = GetContentContext();
248
249 Entity entity;
250 std::optional<Entity> result =
251 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
252 EXPECT_TRUE(result.has_value());
253 if (result.has_value()) {
254 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
255 std::optional<Rect> result_coverage = result.value().GetCoverage();
256 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
257 EXPECT_TRUE(result_coverage.has_value());
258 EXPECT_TRUE(contents_coverage.has_value());
259 if (result_coverage.has_value() && contents_coverage.has_value()) {
260 EXPECT_TRUE(RectNear(contents_coverage.value(),
261 Rect::MakeLTRB(-1, -1, 101, 101)));
262 EXPECT_TRUE(
263 RectNear(result_coverage.value(), Rect::MakeLTRB(-1, -1, 101, 101)));
264 }
265 }
266 }

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

## ◆ TEST_P() [381/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageRotated |
| ) |  |

Definition at line 301 of file gaussian_blur_filter_contents_unittests.cc.

302 {
303 std::shared_ptr<Texture> texture = MakeTexture(ISize(400, 300));
304 fml::StatusOr<Scalar> sigma_radius_1 =
305 CalculateSigmaForBlurRadius(1.0, Matrix());
306 auto contents = std::make_unique<GaussianBlurFilterContents>(
307 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
308 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
309 contents->SetInputs({FilterInput::Make(texture)});
310 std::shared_ptr<ContentContext> renderer = GetContentContext();
311
312 Entity entity;
313 // Rotate around the top left corner, then push it over to (100, 100).
314 entity.SetTransform(Matrix::MakeTranslation({400, 100, 0}) *
315 Matrix::MakeRotationZ(Degrees(90.0)));
316 std::optional<Entity> result =
317 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
318 EXPECT_TRUE(result.has_value());
319 if (result.has_value()) {
320 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
321 std::optional<Rect> result_coverage = result.value().GetCoverage();
322 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
323 EXPECT_TRUE(result_coverage.has_value());
324 EXPECT_TRUE(contents_coverage.has_value());
325 if (result_coverage.has_value() && contents_coverage.has_value()) {
326 EXPECT_TRUE(RectNear(contents_coverage.value(),
327 Rect::MakeLTRB(99, 99, 401, 501)));
328 EXPECT_TRUE(
329 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 99, 401, 501)));
330 }
331 }
332 }

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() [382/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 268 of file gaussian_blur_filter_contents_unittests.cc.

269 {
270 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
271 fml::StatusOr<Scalar> sigma_radius_1 =
272 CalculateSigmaForBlurRadius(1.0, Matrix());
273 ASSERT_TRUE(sigma_radius_1.ok());
274 auto contents = std::make_unique<GaussianBlurFilterContents>(
275 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
276 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
277 contents->SetInputs({FilterInput::Make(texture)});
278 std::shared_ptr<ContentContext> renderer = GetContentContext();
279
280 Entity entity;
281 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
282 std::optional<Entity> result =
283 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
284
285 EXPECT_TRUE(result.has_value());
286 if (result.has_value()) {
287 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
288 std::optional<Rect> result_coverage = result.value().GetCoverage();
289 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
290 EXPECT_TRUE(result_coverage.has_value());
291 EXPECT_TRUE(contents_coverage.has_value());
292 if (result_coverage.has_value() && contents_coverage.has_value()) {
293 EXPECT_TRUE(RectNear(contents_coverage.value(),
294 Rect::MakeLTRB(99, 199, 201, 301)));
295 EXPECT_TRUE(
296 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 199, 201, 301)));
297 }
298 }
299 }

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() [383/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRect |
| ) |  |

Definition at line 347 of file gaussian_blur_filter_contents_unittests.cc.

347 {
348 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
349 auto texture_contents = std::make_shared<TextureContents>();
350 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
351 texture_contents->SetTexture(texture);
352 texture_contents->SetDestinationRect(Rect::MakeXYWH(
353 50, 40, texture->GetSize().width, texture->GetSize().height));
354
355 fml::StatusOr<Scalar> sigma_radius_1 =
356 CalculateSigmaForBlurRadius(1.0, Matrix());
357 auto contents = std::make_unique<GaussianBlurFilterContents>(
358 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
359 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
360 contents->SetInputs({FilterInput::Make(texture_contents)});
361 std::shared_ptr<ContentContext> renderer = GetContentContext();
362
363 Entity entity;
364 std::optional<Entity> result =
365 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
366 EXPECT_TRUE(result.has_value());
367 if (result.has_value()) {
368 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
369 std::optional<Rect> result_coverage = result.value().GetCoverage();
370 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
371 EXPECT_TRUE(result_coverage.has_value());
372 EXPECT_TRUE(contents_coverage.has_value());
373 if (result_coverage.has_value() && contents_coverage.has_value()) {
374 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
375 EXPECT_TRUE(RectNear(result_coverage.value(),
376 Rect::MakeLTRB(49.f, 39.f, 151.f, 141.f)));
377 }
378 }
379 }

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() [384/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRectScaled |
| ) |  |

Definition at line 381 of file gaussian_blur_filter_contents_unittests.cc.

382 {
383 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
384 auto texture_contents = std::make_shared<TextureContents>();
385 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
386 texture_contents->SetTexture(texture);
387 texture_contents->SetDestinationRect(Rect::MakeXYWH(
388 50, 40, texture->GetSize().width, texture->GetSize().height));
389
390 fml::StatusOr<Scalar> sigma_radius_1 =
391 CalculateSigmaForBlurRadius(1.0, Matrix());
392 auto contents = std::make_unique<GaussianBlurFilterContents>(
393 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
394 FilterContents::BlurStyle::kNormal,
395 /*mask_geometry=*/nullptr);
396 contents->SetInputs({FilterInput::Make(texture_contents)});
397 std::shared_ptr<ContentContext> renderer = GetContentContext();
398
399 Entity entity;
400 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
401 std::optional<Entity> result =
402 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
403 EXPECT_TRUE(result.has_value());
404 if (result.has_value()) {
405 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
406 std::optional<Rect> result_coverage = result.value().GetCoverage();
407 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
408 EXPECT_TRUE(result_coverage.has_value());
409 EXPECT_TRUE(contents_coverage.has_value());
410 if (result_coverage.has_value() && contents_coverage.has_value()) {
411 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
412 // Scaling a blurred entity doesn't seem to scale the blur radius linearly
413 // when comparing results with rrect_blur. That's why this is not
414 // Rect::MakeXYWH(98.f, 78.f, 204.0f, 204.f).
415 EXPECT_TRUE(RectNear(contents_coverage.value(),
416 Rect::MakeXYWH(94.f, 74.f, 212.0f, 212.f)));
417 }
418 }
419 }

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() [385/454]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithEffectTransform |
| ) |  |

Definition at line 421 of file gaussian_blur_filter_contents_unittests.cc.

421 {
422 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
423 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
424 auto texture_contents = std::make_shared<TextureContents>();
425 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
426 texture_contents->SetTexture(texture);
427 texture_contents->SetDestinationRect(Rect::MakeXYWH(
428 50, 40, texture->GetSize().width, texture->GetSize().height));
429
430 fml::StatusOr<Scalar> sigma_radius_1 =
431 CalculateSigmaForBlurRadius(1.0, effect_transform);
432 ASSERT_TRUE(sigma_radius_1.ok());
433 auto contents = std::make_unique<GaussianBlurFilterContents>(
434 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
435 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
436 contents->SetInputs({FilterInput::Make(texture_contents)});
437 contents->SetEffectTransform(effect_transform);
438 std::shared_ptr<ContentContext> renderer = GetContentContext();
439
440 Entity entity;
441 std::optional<Entity> result =
442 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
443 EXPECT_TRUE(result.has_value());
444 if (result.has_value()) {
445 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
446 std::optional<Rect> result_coverage = result.value().GetCoverage();
447 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
448 EXPECT_TRUE(result_coverage.has_value());
449 EXPECT_TRUE(contents_coverage.has_value());
450 if (result_coverage.has_value() && contents_coverage.has_value()) {
451 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
452 EXPECT_TRUE(RectNear(contents_coverage.value(),
453 Rect::MakeXYWH(49.f, 39.f, 102.f, 102.f)));
454 }
455 }
456 }

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() [386/454]

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

Definition at line 19 of file host_buffer_unittests.cc.

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

References impeller::HostBuffer::Create().

## ◆ TEST_P() [387/454]

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

Definition at line 34 of file host_buffer_unittests.cc.

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

References impeller::HostBuffer::Create().

## ◆ TEST_P() [388/454]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithFailingAllocationDoesntCrash |
| ) |  |

Definition at line 196 of file host_buffer_unittests.cc.

196 {
197 ScopedValidationDisable disable;
198 std::shared_ptr<FailingAllocator> allocator =
199 std::make_shared<FailingAllocator>(GetContext()->GetResourceAllocator());
200 auto buffer = HostBuffer::Create(allocator);
201
202 auto view = buffer->Emplace(nullptr, kMagicFailingAllocation, 0);
203
204 EXPECT_EQ(view.buffer, nullptr);
205 EXPECT_EQ(view.range.offset, 0u);
206 EXPECT_EQ(view.range.length, 0u);
207 }

References impeller::HostBuffer::Create(), and kMagicFailingAllocation.

## ◆ TEST_P() [389/454]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithProcIsAligned |
| ) |  |

Definition at line 156 of file host_buffer_unittests.cc.

156 {
157 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
158
159 BufferView view = buffer->Emplace(std::array<char, 21>());
160 EXPECT_EQ(view.range, Range(0, 21));
161
162 view = buffer->Emplace(64, 16, [](uint8_t*) {});
163 EXPECT_EQ(view.range, Range(32, 64));
164 }

References impeller::HostBuffer::Create(), and impeller::BufferView::range.

## ◆ TEST_P() [390/454]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBuffer |
| ) |  |

Definition at line 113 of file host_buffer_unittests.cc.

113 {
114 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
115
116 // Emplace an amount larger than the block size, to verify that the host
117 // buffer does not create a buffer.
118 auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0);
119
120 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
121 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
122 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
123 }

References buffer_view, and impeller::HostBuffer::Create().

## ◆ TEST_P() [391/454]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback |
| ) |  |

Definition at line 100 of file host_buffer_unittests.cc.

101 {
102 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
103
104 // Emplace an amount larger than the block size, to verify that the host
105 // buffer does not create a buffer.
106 auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {});
107
108 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
109 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
110 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
111 }

References buffer_view, impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [392/454]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | HostBufferInitialState |
| ) |  |

Definition at line 74 of file host_buffer_unittests.cc.

74 {
75 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
76
77 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
78 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
79 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
80 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [393/454]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | ResetIncrementsFrameCounter |
| ) |  |

Definition at line 82 of file host_buffer_unittests.cc.

82 {
83 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
84
85 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
86
87 buffer->Reset();
88 EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u);
89
90 buffer->Reset();
91 EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u);
92
93 buffer->Reset();
94 EXPECT_EQ(buffer->GetStateForTest().current_frame, 3u);
95
96 buffer->Reset();
97 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
98 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [394/454]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | UnusedBuffersAreDiscardedWhenResetting |
| ) |  |

Definition at line 125 of file host_buffer_unittests.cc.

125 {
126 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
127
128 // Emplace two large allocations to force the allocation of a second buffer.
129 auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
130 auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
131
132 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u);
133 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
134 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
135
136 // Reset until we get back to this frame.
137 for (auto i = 0; i < 4; i++) {
138 buffer->Reset();
139 }
140
141 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
142 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
143 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
144
145 // Now when we reset, the buffer should get dropped.
146 // Reset until we get back to this frame.
147 for (auto i = 0; i < 4; i++) {
148 buffer->Reset();
149 }
150
151 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
152 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
153 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
154 }

References impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [395/454]

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() [396/454]

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() [397/454]

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() [398/454]

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() [399/454]

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() [400/454]

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() [401/454]

impeller::testing::TEST_P | ( | PipelineCacheDataVKPlaygroundTest | ,
|  | CanPersistAndRetrievePipelineCache |
| ) |  |

Definition at line 98 of file pipeline_cache_data_vk_unittests.cc.

98 {
99 fml::ScopedTemporaryDirectory temp_dir;
100 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
101 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
102 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
103
104 {
105 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
106 ASSERT_EQ(cache.result, vk::Result::eSuccess);
107 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
108 ASSERT_TRUE(PipelineCacheDataPersist(
109 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
110 }
111 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
112
113 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(),
114 caps.GetPhysicalDeviceProperties());
115 ASSERT_NE(mapping, nullptr);
116 // Assert that the utility has stripped away the cache header giving us clean
117 // pipeline cache bootstrap information.
118 vk::PipelineCacheHeaderVersionOne vk_cache_header;
119 ASSERT_GE(mapping->GetSize(), sizeof(vk_cache_header));
120 std::memcpy(&vk_cache_header, mapping->GetMapping(), sizeof(vk_cache_header));
121 ASSERT_EQ(vk_cache_header.headerVersion,
122 vk::PipelineCacheHeaderVersion::eOne);
123 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::BackendCast< ContextVK, Context >::Cast(), impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast(), impeller::PipelineCacheDataPersist(), and impeller::PipelineCacheDataRetrieve().

## ◆ TEST_P() [402/454]

impeller::testing::TEST_P | ( | PipelineCacheDataVKPlaygroundTest | ,
|  | IntegrityChecksArePerformedOnPersistedData |
| ) |  |

Definition at line 125 of file pipeline_cache_data_vk_unittests.cc.

126 {
127 fml::ScopedTemporaryDirectory temp_dir;
128 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
129 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
130 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
131
132 {
133 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
134 ASSERT_EQ(cache.result, vk::Result::eSuccess);
135 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
136 ASSERT_TRUE(PipelineCacheDataPersist(
137 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
138 }
139 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
140 auto incompatible_caps = caps.GetPhysicalDeviceProperties();
141 // Simulate a driver version bump.
142 incompatible_caps.driverVersion =
143 caps.GetPhysicalDeviceProperties().driverVersion + 1u;
144 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(), incompatible_caps);
145 ASSERT_EQ(mapping, nullptr);
146 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::BackendCast< ContextVK, Context >::Cast(), impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast(), impeller::PipelineCacheDataPersist(), and impeller::PipelineCacheDataRetrieve().

## ◆ TEST_P() [403/454]

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() [404/454]

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() [405/454]

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() [406/454]

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() [407/454]

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() [408/454]

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() [409/454]

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() [410/454]

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() [411/454]

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() [412/454]

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 Playground::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() [413/454]

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 Playground::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() [414/454]

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() [415/454]

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 Playground::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() [416/454]

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() [417/454]

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() [418/454]

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() [419/454]

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() [420/454]

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() [421/454]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1482 of file renderer_unittests.cc.

1482 {
1483 // Define shader types
1484 using TextureVS = TextureVertexShader;
1485 using TextureFS = TextureFragmentShader;
1486
1487 using SwizzleVS = SepiaVertexShader;
1488 using SwizzleFS = SwizzleFragmentShader;
1489
1490 using SepiaVS = SepiaVertexShader;
1491 using SepiaFS = SepiaFragmentShader;
1492
1493 auto context = GetContext();
1494 ASSERT_TRUE(context);
1495
1496 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1497 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1498 "support it.";
1499 return;
1500 }
1501
1502 // Create pipelines.
1503 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1504 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1505 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1506
1507 ASSERT_TRUE(texture_pipeline);
1508 ASSERT_TRUE(swizzle_pipeline);
1509 ASSERT_TRUE(sepia_pipeline);
1510
1511 // Vertex buffer builders.
1512 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1513 texture_vtx_builder.AddVertices({
1514 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1515 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1516 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1517 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1518 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1519 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1520 });
1521
1522 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1523 sepia_vtx_builder.AddVertices({
1524 {{100, 100, 0.0}}, // 1
1525 {{800, 100, 0.0}}, // 2
1526 {{800, 800, 0.0}}, // 3
1527 {{100, 100, 0.0}}, // 1
1528 {{800, 800, 0.0}}, // 3
1529 {{100, 800, 0.0}}, // 4
1530 });
1531
1532 auto boston = CreateTextureForFixture("boston.jpg");
1533 ASSERT_TRUE(boston);
1534
1535 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1536 ASSERT_TRUE(sampler);
1537
1538 SinglePassCallback callback = [&](RenderPass& pass) {
1539 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1540
1541 // Draw the texture.
1542 {
1543 pass.SetPipeline(texture_pipeline);
1544 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1545 *context->GetResourceAllocator()));
1546 TextureVS::UniformBuffer uniforms;
1547 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1548 Matrix::MakeScale(GetContentScale());
1549 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1550 TextureFS::BindTextureContents(pass, boston, sampler);
1551 if (!pass.Draw().ok()) {
1552 return false;
1553 }
1554 }
1555
1556 // Draw the sepia toner.
1557 {
1558 pass.SetPipeline(sepia_pipeline);
1559 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1560 *context->GetResourceAllocator()));
1561 SepiaVS::UniformBuffer uniforms;
1562 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1563 Matrix::MakeScale(GetContentScale());
1564 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1565 if (!pass.Draw().ok()) {
1566 return false;
1567 }
1568 }
1569
1570 // Draw the swizzle.
1571 {
1572 pass.SetPipeline(swizzle_pipeline);
1573 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1574 *context->GetResourceAllocator()));
1575 SwizzleVS::UniformBuffer uniforms;
1576 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1577 Matrix::MakeScale(GetContentScale());
1578 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1579 if (!pass.Draw().ok()) {
1580 return false;
1581 }
1582 }
1583
1584 return true;
1585 };
1586 OpenPlaygroundHere(callback);
1587 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [422/454]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneWithSubpasses |
| ) |  |

Definition at line 1394 of file renderer_unittests.cc.

1394 {
1395 // Define shader types
1396 using TextureVS = TextureVertexShader;
1397 using TextureFS = TextureFragmentShader;
1398
1399 using SepiaVS = SepiaVertexShader;
1400 using SepiaFS = SepiaFragmentShader;
1401
1402 auto context = GetContext();
1403 ASSERT_TRUE(context);
1404
1405 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1406 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1407 "support it.";
1408 return;
1409 }
1410
1411 // Create pipelines.
1412 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1413 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1414
1415 ASSERT_TRUE(texture_pipeline);
1416 ASSERT_TRUE(sepia_pipeline);
1417
1418 // Vertex buffer builders.
1419 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1420 texture_vtx_builder.AddVertices({
1421 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1422 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1423 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1424 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1425 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1426 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1427 });
1428
1429 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1430 sepia_vtx_builder.AddVertices({
1431 {{100, 100, 0.0}}, // 1
1432 {{800, 100, 0.0}}, // 2
1433 {{800, 800, 0.0}}, // 3
1434 {{100, 100, 0.0}}, // 1
1435 {{800, 800, 0.0}}, // 3
1436 {{100, 800, 0.0}}, // 4
1437 });
1438
1439 auto boston = CreateTextureForFixture("boston.jpg");
1440 ASSERT_TRUE(boston);
1441
1442 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1443 ASSERT_TRUE(sampler);
1444
1445 SinglePassCallback callback = [&](RenderPass& pass) {
1446 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1447
1448 // Draw the texture.
1449 {
1450 pass.SetPipeline(texture_pipeline);
1451 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1452 *context->GetResourceAllocator()));
1453 TextureVS::UniformBuffer uniforms;
1454 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1455 Matrix::MakeScale(GetContentScale());
1456 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1457 TextureFS::BindTextureContents(pass, boston, sampler);
1458 if (!pass.Draw().ok()) {
1459 return false;
1460 }
1461 }
1462
1463 // Draw the sepia toner.
1464 {
1465 pass.SetPipeline(sepia_pipeline);
1466 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1467 *context->GetResourceAllocator()));
1468 SepiaVS::UniformBuffer uniforms;
1469 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1470 Matrix::MakeScale(GetContentScale());
1471 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1472 if (!pass.Draw().ok()) {
1473 return false;
1474 }
1475 }
1476
1477 return true;
1478 };
1479 OpenPlaygroundHere(callback);
1480 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [423/454]

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() [424/454]

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() [425/454]

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() [426/454]

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() [427/454]

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() [428/454]

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 Playground::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() [429/454]

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() [430/454]

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() [431/454]

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() [432/454]

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() [433/454]

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() [434/454]

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() [435/454]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanCreatePipelineFromRuntimeStage |
| ) |  |

Definition at line 315 of file runtime_stage_unittests.cc.

315 {
316 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
317 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
318
319 ASSERT_TRUE(stage);
320 ASSERT_NE(stage, nullptr);
321 ASSERT_TRUE(RegisterStage(*stage));
322 auto library = GetContext()->GetShaderLibrary();
323 using VS = RuntimeEffectVertexShader;
324 PipelineDescriptor desc;
325 desc.SetLabel("Runtime Stage InkSparkle");
326 desc.AddStageEntrypoint(
327 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
328 desc.AddStageEntrypoint(
329 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
330 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
331 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
332 VS::kInterleavedBufferLayout);
333
334 std::array<DescriptorSetLayout, 2> descriptor_set_layouts = {
335 VS::kDescriptorSetLayouts[0],
336 DescriptorSetLayout{
337 .binding = 64u,
338 .descriptor_type = DescriptorType::kUniformBuffer,
339 .shader_stage = ShaderStage::kFragment,
340 },
341 };
342 vertex_descriptor->RegisterDescriptorSetLayouts(descriptor_set_layouts);
343
344 desc.SetVertexDescriptor(std::move(vertex_descriptor));
345 ColorAttachmentDescriptor color0;
346 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
347 StencilAttachmentDescriptor stencil0;
348 stencil0.stencil_compare = CompareFunction::kEqual;
349 desc.SetColorAttachmentDescriptor(0u, color0);
350 desc.SetStencilAttachmentDescriptors(stencil0);
351 const auto stencil_fmt =
352 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
353 desc.SetStencilPixelFormat(stencil_fmt);
354 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
355 ASSERT_NE(pipeline, nullptr);
356 }

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() [436/454]

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

Definition at line 56 of file runtime_stage_unittests.cc.

56 {
57 const std::shared_ptr<fml::Mapping> fixture =
58 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
59 ASSERT_TRUE(fixture);
60 ASSERT_GT(fixture->GetSize(), 0u);
61 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
62 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
63
64 ASSERT_TRUE(stage->IsValid());
65 switch (GetBackend()) {
66 case PlaygroundBackend::kMetal:
67 [[fallthrough]];
68 case PlaygroundBackend::kOpenGLES: {
69 ASSERT_EQ(stage->GetUniforms().size(), 17u);
70 {
71 auto uni = stage->GetUniform("u_color");
72 ASSERT_NE(uni, nullptr);
73 EXPECT_EQ(uni->dimensions.rows, 4u);
74 EXPECT_EQ(uni->dimensions.cols, 1u);
75 EXPECT_EQ(uni->location, 0u);
76 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
77 }
78 {
79 auto uni = stage->GetUniform("u_alpha");
80 ASSERT_NE(uni, nullptr);
81 EXPECT_EQ(uni->dimensions.rows, 1u);
82 EXPECT_EQ(uni->dimensions.cols, 1u);
83 EXPECT_EQ(uni->location, 1u);
84 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
85 }
86 {
87 auto uni = stage->GetUniform("u_sparkle_color");
88 ASSERT_NE(uni, nullptr);
89 EXPECT_EQ(uni->dimensions.rows, 4u);
90 EXPECT_EQ(uni->dimensions.cols, 1u);
91 EXPECT_EQ(uni->location, 2u);
92 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
93 }
94 {
95 auto uni = stage->GetUniform("u_sparkle_alpha");
96 ASSERT_NE(uni, nullptr);
97 EXPECT_EQ(uni->dimensions.rows, 1u);
98 EXPECT_EQ(uni->dimensions.cols, 1u);
99 EXPECT_EQ(uni->location, 3u);
100 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
101 }
102 {
103 auto uni = stage->GetUniform("u_blur");
104 ASSERT_NE(uni, nullptr);
105 EXPECT_EQ(uni->dimensions.rows, 1u);
106 EXPECT_EQ(uni->dimensions.cols, 1u);
107 EXPECT_EQ(uni->location, 4u);
108 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
109 }
110 {
111 auto uni = stage->GetUniform("u_radius_scale");
112 ASSERT_NE(uni, nullptr);
113 EXPECT_EQ(uni->dimensions.rows, 1u);
114 EXPECT_EQ(uni->dimensions.cols, 1u);
115 EXPECT_EQ(uni->location, 6u);
116 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
117 }
118 {
119 auto uni = stage->GetUniform("u_max_radius");
120 ASSERT_NE(uni, nullptr);
121 EXPECT_EQ(uni->dimensions.rows, 1u);
122 EXPECT_EQ(uni->dimensions.cols, 1u);
123 EXPECT_EQ(uni->location, 7u);
124 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
125 }
126 {
127 auto uni = stage->GetUniform("u_resolution_scale");
128 ASSERT_NE(uni, nullptr);
129 EXPECT_EQ(uni->dimensions.rows, 2u);
130 EXPECT_EQ(uni->dimensions.cols, 1u);
131 EXPECT_EQ(uni->location, 8u);
132 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
133 }
134 {
135 auto uni = stage->GetUniform("u_noise_scale");
136 ASSERT_NE(uni, nullptr);
137 EXPECT_EQ(uni->dimensions.rows, 2u);
138 EXPECT_EQ(uni->dimensions.cols, 1u);
139 EXPECT_EQ(uni->location, 9u);
140 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
141 }
142 {
143 auto uni = stage->GetUniform("u_noise_phase");
144 ASSERT_NE(uni, nullptr);
145 EXPECT_EQ(uni->dimensions.rows, 1u);
146 EXPECT_EQ(uni->dimensions.cols, 1u);
147 EXPECT_EQ(uni->location, 10u);
148 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
149 }
150
151 {
152 auto uni = stage->GetUniform("u_circle1");
153 ASSERT_NE(uni, nullptr);
154 EXPECT_EQ(uni->dimensions.rows, 2u);
155 EXPECT_EQ(uni->dimensions.cols, 1u);
156 EXPECT_EQ(uni->location, 11u);
157 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
158 }
159 {
160 auto uni = stage->GetUniform("u_circle2");
161 ASSERT_NE(uni, nullptr);
162 EXPECT_EQ(uni->dimensions.rows, 2u);
163 EXPECT_EQ(uni->dimensions.cols, 1u);
164 EXPECT_EQ(uni->location, 12u);
165 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
166 }
167 {
168 auto uni = stage->GetUniform("u_circle3");
169 ASSERT_NE(uni, nullptr);
170 EXPECT_EQ(uni->dimensions.rows, 2u);
171 EXPECT_EQ(uni->dimensions.cols, 1u);
172 EXPECT_EQ(uni->location, 13u);
173 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
174 }
175 {
176 auto uni = stage->GetUniform("u_rotation1");
177 ASSERT_NE(uni, nullptr);
178 EXPECT_EQ(uni->dimensions.rows, 2u);
179 EXPECT_EQ(uni->dimensions.cols, 1u);
180 EXPECT_EQ(uni->location, 14u);
181 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
182 }
183 {
184 auto uni = stage->GetUniform("u_rotation2");
185 ASSERT_NE(uni, nullptr);
186 EXPECT_EQ(uni->dimensions.rows, 2u);
187 EXPECT_EQ(uni->dimensions.cols, 1u);
188 EXPECT_EQ(uni->location, 15u);
189 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
190 }
191 {
192 auto uni = stage->GetUniform("u_rotation3");
193 ASSERT_NE(uni, nullptr);
194 EXPECT_EQ(uni->dimensions.rows, 2u);
195 EXPECT_EQ(uni->dimensions.cols, 1u);
196 EXPECT_EQ(uni->location, 16u);
197 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
198 }
199 break;
200 }
201 case PlaygroundBackend::kVulkan: {
202 EXPECT_EQ(stage->GetUniforms().size(), 1u);
203 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
204 ASSERT_TRUE(uni);
205 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
206 EXPECT_EQ(uni->struct_float_count, 32u);
207
208 // There are 36 4 byte chunks in the UBO: 32 for the 32 floats, and 4 for
209 // padding. Initialize a vector as if they'll all be floats, then manually
210 // set the few padding bytes. If the shader changes, the padding locations
211 // will change as well. For example, if `u_alpha` was moved to the end,
212 // three bytes of padding could potentially be dropped - or if some of the
213 // scalar floats were changed to vec2 or vec4s, or if any vec3s are
214 // introduced.
215 // This means 36 * 4 = 144 bytes total.
216
217 EXPECT_EQ(uni->GetSize(), 144u);
218 std::vector<uint8_t> layout(uni->GetSize() / sizeof(float), 1);
219 layout[5] = 0;
220 layout[6] = 0;
221 layout[7] = 0;
222 layout[23] = 0;
223
224 EXPECT_THAT(uni->struct_layout, ::testing::ElementsAreArray(layout));
225 break;
226 }
227 }
228 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFloat, impeller::kMetal, impeller::kOpenGLES, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [437/454]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerAfterUBO |
| ) |  |

Definition at line 255 of file runtime_stage_unittests.cc.

255 {
256 if (GetBackend() != PlaygroundBackend::kVulkan) {
257 GTEST_SKIP() << "Test only relevant for Vulkan";
258 }
259 const std::shared_ptr<fml::Mapping> fixture =
260 flutter::testing::OpenFixtureAsMapping(
261 "uniforms_and_sampler_2.frag.iplr");
262 ASSERT_TRUE(fixture);
263 ASSERT_GT(fixture->GetSize(), 0u);
264 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
265 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
266
267 EXPECT_EQ(stage->GetUniforms().size(), 2u);
268 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
269 ASSERT_TRUE(uni);
270 // Struct must be offset at 45.
271 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
272 EXPECT_EQ(uni->binding, 64u);
273 // Sampler should be offset at 64 but due to current bug
274 // has offset of 0, the correct offset is computed at runtime.
275 auto sampler_uniform = stage->GetUniform("u_texture");
276 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
277 EXPECT_EQ(sampler_uniform->binding, 65u);
278 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [438/454]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerBeforeUBO |
| ) |  |

Definition at line 230 of file runtime_stage_unittests.cc.

230 {
231 if (GetBackend() != PlaygroundBackend::kVulkan) {
232 GTEST_SKIP() << "Test only relevant for Vulkan";
233 }
234 const std::shared_ptr<fml::Mapping> fixture =
235 flutter::testing::OpenFixtureAsMapping(
236 "uniforms_and_sampler_1.frag.iplr");
237 ASSERT_TRUE(fixture);
238 ASSERT_GT(fixture->GetSize(), 0u);
239 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
240 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
241
242 EXPECT_EQ(stage->GetUniforms().size(), 2u);
243 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
244 ASSERT_TRUE(uni);
245 // Struct must be offset at 65.
246 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
247 EXPECT_EQ(uni->binding, 65u);
248 // Sampler should be offset at 64 but due to current bug
249 // has offset of 0, the correct offset is computed at runtime.
250 auto sampler_uniform = stage->GetUniform("u_texture");
251 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
252 EXPECT_EQ(sampler_uniform->binding, 64u);
253 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [439/454]

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() [440/454]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRegisterStage |
| ) |  |

Definition at line 280 of file runtime_stage_unittests.cc.

280 {
281 const std::shared_ptr<fml::Mapping> fixture =
282 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
283 ASSERT_TRUE(fixture);
284 ASSERT_GT(fixture->GetSize(), 0u);
285 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
286 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
287 ASSERT_TRUE(stage->IsValid());
288 std::promise<bool> registration;
289 auto future = registration.get_future();
290 auto library = GetContext()->GetShaderLibrary();
291 library->RegisterFunction(
292 stage->GetEntrypoint(), //
293 ToShaderStage(stage->GetShaderStage()), //
294 stage->GetCodeMapping(), //
295 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
296 reg.set_value(result);
297 }));
298 ASSERT_TRUE(future.get());
299 {
300 auto function =
301 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
302 ASSERT_NE(function, nullptr);
303 }
304
305 // Check if unregistering works.
306
307 library->UnregisterFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
308 {
309 auto function =
310 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
311 ASSERT_EQ(function, nullptr);
312 }
313 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::ToShaderStage().

## ◆ TEST_P() [441/454]

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(Bytes{fixture->GetSize()}, false));
47 // Not meant to be secure. Just reject obviously bad blobs using magic
48 // numbers.
49 ::memset(junk_allocation->GetBuffer(), 127,
50 junk_allocation->GetLength().GetByteSize());
51 auto stages = RuntimeStage::DecodeRuntimeStages(
52 CreateMappingFromAllocation(junk_allocation));
53 ASSERT_FALSE(stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())]);
54 }

References impeller::CreateMappingFromAllocation(), impeller::RuntimeStage::DecodeRuntimeStages(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [442/454]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | ContainsExpectedShaderTypes |
| ) |  |

Definition at line 358 of file runtime_stage_unittests.cc.

358 {
359 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
360 // Right now, SkSL gets implicitly bundled regardless of what the build rule
361 // for this test requested. After
362 // https://github.com/flutter/flutter/issues/138919, this may require a build
363 // rule change or a new test.
364 EXPECT_TRUE(stages[RuntimeStageBackend::kSkSL]);
365
366 EXPECT_TRUE(stages[RuntimeStageBackend::kOpenGLES]);
367 EXPECT_TRUE(stages[RuntimeStageBackend::kMetal]);
368 EXPECT_TRUE(stages[RuntimeStageBackend::kVulkan]);
369 }

References impeller::kMetal, impeller::kOpenGLES, impeller::kSkSL, and impeller::kVulkan.

## ◆ TEST_P() [443/454]

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() [444/454]

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() [445/454]

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() [446/454]

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() [447/454]

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() [448/454]

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 SkFont sk_font_small = flutter::testing::CreateTestFontOfSize(10);
457
458 for (int i = 0; i < 13; i++) {
459 SkTextBlobBuilder builder;
460
461 auto add_char = [&](const SkFont& sk_font, char c) {
462 int count = sk_font.countText(&c, 1, SkTextEncoding::kUTF8);
463 auto buffer = builder.allocRunPos(sk_font, count);
464 sk_font.textToGlyphs(&c, 1, SkTextEncoding::kUTF8, buffer.glyphs, count);
465 sk_font.getPos(buffer.glyphs, count, buffer.points(), {0, 0});
466 };
467
468 SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
469 add_char(sk_font, 'A');
470 add_char(sk_font_small, 'B');
471 auto blob = builder.make();
472
473 atlas =
474 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
475 GlyphAtlas::Type::kAlphaBitmap, 50 + i, atlas_context,
476 *MakeTextFrameFromTextBlobSkia(blob));
477 ASSERT_TRUE(!!atlas);
478 EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
479 expected_sizes[i]);
480 }
481
482 // The final atlas should contain both the "A" glyph (which was not present
483 // in the previous atlas) and the "B" glyph (which existed in the previous
484 // atlas).
485 ASSERT_EQ(atlas->GetGlyphCount(), 2u);
486 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [449/454]

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() [450/454]

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() [451/454]

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() [452/454]

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() [453/454]

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

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

Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 281 of file aiks_dl_text_unittests.cc.

Referenced by TEST_P().

## ◆ kMagicFailingAllocation

constexpr const size_t impeller::testing::kMagicFailingAllocation = 1024000 * 2
| staticconstexpr

Definition at line 166 of file host_buffer_unittests.cc.

Referenced by impeller::testing::FailingAllocator::OnCreateBuffer(), and TEST_P().

## ◆ kPaintVariations

const std::map<std::string, MaskBlurTestConfig> impeller::testing::kPaintVariations
| static

Definition at line 484 of file aiks_dl_blur_unittests.cc.

impeller::testing::kMagicFailingAllocation
static constexpr const size_t kMagicFailingAllocation
Definition: host_buffer_unittests.cc:166
impeller::ISize
ISize64 ISize
Definition: size.h:140
_BLEND_MODE_RESULT_CHECK
#define _BLEND_MODE_RESULT_CHECK(blend_mode)
Definition: geometry_unittests.cc:1640
NumberNear
bool NumberNear(double a, double b)
Definition: geometry_asserts.h:18
impeller::testing::RenderTextInCanvasSkia
bool RenderTextInCanvasSkia(const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string_view &font_fixture, const TextRenderOptions &options={})
Definition: aiks_dl_text_unittests.cc:41
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
impeller::PipelineCacheDataPersist
bool PipelineCacheDataPersist(const fml::UniqueFD &cache_directory, const VkPhysicalDeviceProperties &props, const vk::UniquePipelineCache &cache)
Persist the pipeline cache to a file in the given cache directory. This function performs integrity c...
Definition: pipeline_cache_data_vk.cc:16
polyline
const Path::Polyline & polyline
Definition: stroke_path_geometry.cc:296
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::testing::CreateTestCanvas
std::unique_ptr< Canvas > CreateTestCanvas(ContentContext &context, std::optional< Rect > cull_rect=std::nullopt)
Definition: canvas_unittests.cc:13
impeller::skia_conversions::IsNearlySimpleRRect
bool IsNearlySimpleRRect(const SkRRect &rr)
Like SkRRect.isSimple, but allows the corners to differ by kEhCloseEnough.
Definition: skia_conversions.cc:21
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
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< SubpixelGlyph, SubpixelGlyph::Hash, SubpixelGlyph::Equal >, ScaledFont::Hash, ScaledFont::Equal > FontGlyphMap
Definition: font_glyph_pair.h:108
uvs
Quad uvs
Definition: gaussian_blur_filter_contents.cc:204
impeller::KiloBytes
AllocationSize< 1 '000u > KiloBytes
Definition: allocation_size.h:153
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:144
impeller::testing::swap_nan
static constexpr Point swap_nan(const Point &point, int index)
Definition: rect_unittests.cc:1336
impeller::skia_conversions::ToSize
Size ToSize(const SkPoint &point)
Definition: skia_conversions.cc:102
impeller::BlendMode
BlendMode
Definition: color.h:58
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
impeller::MebiBytes
AllocationSize< 1 '024u *1 '024u > MebiBytes
Definition: allocation_size.h:158
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
font_size
SkScalar font_size
Definition: dl_golden_blur_unittests.cc:23
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::ComputeSaveLayerCoverage
std::optional< Rect > ComputeSaveLayerCoverage(const Rect &content_coverage, const Matrix &effect_transform, const Rect &coverage_limit, const std::shared_ptr< FilterContents > &image_filter, bool flood_output_coverage, bool flood_input_coverage)
Compute the coverage of a subpass in the global coordinate space.
Definition: save_layer_utils.cc:16
impeller::TPoint::Round
static constexpr TPoint Round(const TPoint< U > &other)
Definition: point.h:49
impeller::Vector2
Point Vector2
Definition: point.h:331
EXPECT_POINT_NEAR
#define EXPECT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:205
impeller::skia_conversions::ToMatrix
Matrix ToMatrix(const SkMatrix &m)
Definition: skia_conversions.cc:193
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:1322
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:106
impeller::UintPoint32
TPoint< uint32_t > UintPoint32
Definition: point.h:330
padding
Vector2 padding
The halo padding in source space.
Definition: gaussian_blur_filter_contents.cc:85
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:128
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::GetMaliVersion
MaliGPU GetMaliVersion(std::string_view version)
Definition: driver_info_vk.cc:122
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:17
impeller::CreateMappingFromAllocation
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Creates a mapping from 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:32
stroke_width
const Scalar stroke_width
Definition: stroke_path_geometry.cc:297
impeller::GibiBytes
AllocationSize< 1 '024u *1 '024u *1 '024u > GibiBytes
Definition: allocation_size.h:159
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:304
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::skia_conversions::ToBlendMode
BlendMode ToBlendMode(flutter::DlBlendMode mode)
Definition: skia_conversions.cc:204
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32
impeller::TRect::Shift
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition: rect.h:596
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::MinMagFilter::kNearest
@ kNearest
Select nearest to the sample point. Most widely supported.
impeller::kPhi
constexpr float kPhi
Definition: constants.h:53
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:16
impeller::OptionsFromPassAndEntity
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:34
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::testing::DoGradientOvalStrokeMaskBlur
sk_sp< flutter::DisplayList > DoGradientOvalStrokeMaskBlur(Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
Definition: aiks_dl_blur_unittests.cc:63
impeller::ToSamplerDescriptor
static impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlFilterMode options)
Definition: dl_dispatcher.cc:118
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::k2Pi
constexpr float k2Pi
Definition: constants.h:29
impeller::Quad
std::array< Point, 4 > Quad
Definition: point.h:332
impeller::KibiBytes
AllocationSize< 1 '024u > KibiBytes
Definition: allocation_size.h:157
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1177
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1642
impeller::MipFilter
MipFilter
Options for selecting and filtering between mipmap levels.
Definition: formats.h:425
impeller::testing::flip_lr
static constexpr R flip_lr(R rect)
Definition: rect_unittests.cc:1310
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:213
impeller::testing::GetBlendModeSelection
static BlendModeSelection GetBlendModeSelection()
Definition: aiks_dl_blend_unittests.cc:45
impeller::IPoint32
TPoint< int32_t > IPoint32
Definition: point.h:329
impeller::ScalarToHalf
constexpr InternalHalf ScalarToHalf(Scalar f)
Convert a scalar to a half precision float.
Definition: half.h:32
impeller::MinMagFilter::kLinear
@ kLinear
impeller::TPoint::Max
constexpr TPoint Max(const TPoint &p) const
Definition: point.h:190
type
GLenum type
Definition: blit_command_gles.cc:127
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:415
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1659
_BLEND_MODE_NAME_CHECK
#define _BLEND_MODE_NAME_CHECK(blend_mode)
Definition: geometry_unittests.cc:1658
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:776
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:98
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:19
impeller::MakeTextFrameFromTextBlobSkia
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
Definition: text_frame_skia.cc:42
impeller::ContentContextOptions::primitive_type
PrimitiveType primitive_type
Definition: content_context.h:311
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:886
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:91
impeller::MegaBytes
AllocationSize< 1 '000u *1 '000u > MegaBytes
Definition: allocation_size.h:154
impeller::LineTo
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24
impeller::Join
Join
Definition: path.h:24
impeller::MipFilter::kBase
@ kBase
The texture is sampled as if it only had a single mipmap level.
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
BLEND_MODE_TUPLE
#define BLEND_MODE_TUPLE(blend_mode)
Definition: aiks_dl_blend_unittests.cc:38
impeller::IPoint
TPoint< int64_t > IPoint
Definition: point.h:328
impeller::PipelineCacheDataRetrieve
std::unique_ptr< fml::Mapping > PipelineCacheDataRetrieve(const fml::UniqueFD &cache_directory, const VkPhysicalDeviceProperties &props)
Retrieve the previously persisted pipeline cache data. This function provides integrity checks the Vu...
Definition: pipeline_cache_data_vk.cc:58
impeller::MyMaskBits
MyMaskBits
Definition: base_unittests.cc:13
ASSERT_VECTOR3_NEAR
#define ASSERT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:194
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::testing::kFontFixture
static constexpr std::string_view kFontFixture
Definition: aiks_dl_text_unittests.cc:281
impeller::MipFilter::kLinear
@ kLinear
Sample from the two nearest mip levels and linearly interpolate.
impeller::GetAdrenoVersion
AdrenoGPU GetAdrenoVersion(std::string_view version)
Definition: driver_info_vk.cc:108
scale
const Scalar scale
Definition: stroke_path_geometry.cc:301
blur_radius
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Definition: gaussian_blur_filter_contents.cc:83
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:35
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:54
impeller::LerpHackKernelSamples
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
Definition: gaussian_blur_filter_contents.cc:933
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:779
color
DlColor color
Definition: dl_golden_blur_unittests.cc:24
impeller::DisplayListToTexture
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips)
Render the provided display list to a texture with the given size.
Definition: dl_dispatcher.cc:1195
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::testing::RenderTextInCanvasSTB
bool RenderTextInCanvasSTB(const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string &font_fixture, const TextRenderOptions &options={})
Definition: aiks_dl_text_unittests.cc:84
impeller::TSize::MipCount
constexpr size_t MipCount() const
Definition: size.h:115
impeller::GigaBytes
AllocationSize< 1 '000u *1 '000u *1 '000u > GigaBytes
Definition: allocation_size.h:155
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:208
impeller::interop::Create
ScopedObject< Object > Create(CtorArgs &&... args)
Definition: object.h:160
impeller::testing::flip_tb
static constexpr R flip_tb(R rect)
Definition: rect_unittests.cc:1316
ASSERT_COLOR_BUFFER_NEAR
#define ASSERT_COLOR_BUFFER_NEAR(a, b)
Definition: geometry_asserts.h:198
impeller::DlScalar
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:21
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::AllocationSize::GetSize
constexpr double GetSize() const
Definition: allocation_size.h:76
impeller::Bytes
AllocationSize< 1u > Bytes
Definition: allocation_size.h:151
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
impeller::testing::IsBadVersionTest
bool IsBadVersionTest(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:52