| 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 | MockIdleWaiter
class | RendererDartTest
struct | RWFoo
class | Screenshot
class | Screenshotter
class | TestAllocator
struct | TextRenderOptions
class | VulkanScreenshotter
class | WorkingDirectory

## Typedefs
using | AiksTest = AiksPlayground
using | DisplayListTest = DlPlayground
using | HostBufferTest = EntityPlayground
using | TextContentsTest = PlaygroundTest
using | EntityTest = EntityPlayground
using | EntityPassTargetTest = EntityPlayground
using | RenderTargetCacheTest = EntityPlayground
using | SaveLayerUtilsTest = ::testing::Test
using | AllocatorMTLTest = PlaygroundTest
using | SwapchainTransientsMTLTest = PlaygroundTest
using | DriverInfoVKTest = PlaygroundTest
using | PipelineCacheDataVKPlaygroundTest = PlaygroundTest
using | RendererTest = PlaygroundTest
using | BlitPassTest = AiksTest
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 (BufferViewTest, Empty)
| TEST (BufferViewTest, TakeRaw)
| 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, DrawImageRectSrcOutsideBounds)
| 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)
| TEST_P (AiksTest, NoDimplesInRRectPath)
| TEST_P (AiksTest, BackdropFilterOverUnclosedClip)
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, DestructiveBlendColorFilterFloodsClip)
| TEST_P (AiksTest, AdvancedBlendColorFilterWithDestinationOpacity)
| 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, CanRenderBackdropBlurWithSingleBackdropId)
| TEST_P (AiksTest, CanRenderMultipleBackdropBlurWithSingleBackdropId)
| TEST_P (AiksTest, CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters)
| 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)
| TEST_P (AiksTest, MaskBlurOnZeroDimensionIsSkippedWideGamut)
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, CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers)
| 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, CanRenderLinearGradientWithIncompleteStops)
| TEST_P (AiksTest, CanRenderRadialGradientWithIncompleteStops)
| TEST_P (AiksTest, CanRenderConicalGradientWithIncompleteStops)
| TEST_P (AiksTest, CanRenderSweepGradientWithIncompleteStops)
| 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, FatStrokeArc)
| TEST_P (AiksTest, CanRenderOverlappingMultiContourPath)
| TEST_P (AiksTest, CanRenderClippedRuntimeEffects)
| TEST_P (AiksTest, DrawPaintTransformsBounds)
| TEST_P (AiksTest, CanRenderRuntimeEffectFilter)
bool | RenderTextInCanvasSkia (const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string_view &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, 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, DifferenceClipsMustRenderIdenticallyAcrossBackends)
| 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, DepthValuesForLineMode)
| TEST_P (AiksTest, DepthValuesForPolygonMode)
| TEST_P (AiksTest, ToImageFromImage)
| 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, bool requires_readback=false)
| TEST_P (AiksTest, TransformMultipliesCorrectly)
| TEST_P (AiksTest, CanvasCanPushPopCTM)
| TEST_P (AiksTest, CanvasCTMCanBeUpdated)
| TEST_P (AiksTest, BackdropCountDownNormal)
| TEST_P (AiksTest, BackdropCountDownBackdropId)
| TEST_P (AiksTest, BackdropCountDownBackdropIdMixed)
| TEST_P (AiksTest, BackdropCountDownWithNestedSaveLayers)
| TEST_P (AiksTest, DrawVerticesLinearGradientWithEmptySize)
| TEST_P (AiksTest, DrawVerticesWithEmptyTextureCoordinates)
| TEST_P (AiksTest, SupportsBlitToOnscreen)
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 (EntityPassClipStackTest, CanPushAndPopEntities)
| TEST (EntityPassClipStackTest, CanPopEntitiesSafely)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverage)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverageNonAA)
| TEST (EntityPassClipStackTest, AppendLargerClipCoverage)
| TEST (EntityPassClipStackTest, AppendLargerClipCoverageWithDifferenceOrNonSquare)
| TEST (EntityPassClipStackTest, AppendDecreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, AppendIncreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, UnbalancedRestore)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpasses)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpassesNonAA)
| 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)
| INSTANTIATE_PLAYGROUND_SUITE (MatrixFilterContentsTest)
| 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, IdleWaiter)
| 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)
| INSTANTIATE_PLAYGROUND_SUITE (TextContentsTest)
| TEST_P (TextContentsTest, SimpleComputeVertexData)
| TEST_P (TextContentsTest, SimpleComputeVertexData2x)
| TEST_P (TextContentsTest, MaintainsShape)
| 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_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, 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, DrawRoundSuperEllipse)
| 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_P (EntityTest, GiantStrokePathAllocation)
| TEST_P (EntityTest, GiantLineStripPathAllocation)
| 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, CachesUsedTexturesAcrossFramesWithKeepAlive)
| 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 (SaveLayerUtilsTest, RoundUpCoverageWhenCloseToCoverageLimit)
| TEST (SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitWidth)
| TEST (SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitHeight)
| TEST (SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitWidthHeight)
| 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, Vector4IsFinite)
| 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, IsTranslationOnly)
| TEST (MatrixTest, IsTranslationScaleOnly)
| TEST (MatrixTest, IsInvertibleGetDeterminant)
| TEST (MatrixTest, IsFinite)
| TEST (MatrixTest, IsAligned2D)
| TEST (MatrixTest, IsAligned)
| TEST (MatrixTest, TransformHomogenous)
| TEST (MatrixTest, GetMaxBasisXYNegativeScale)
| TEST (MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactor)
| TEST (MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactorNonScaleTranslate)
| TEST (MatrixTest, TranslateWithPerspective)
| TEST (MatrixTest, MakeScaleTranslate)
| TEST (PathTest, CubicPathComponentPolylineDoesNotIncludePointOne)
| TEST (PathTest, EmptyPathWithContour)
| TEST (PathTest, PathCreatePolyLineDoesNotDuplicatePoints)
| TEST (PathTest, PathSingleContour)
| TEST (PathTest, PathSingleContourDoubleShapes)
| 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, FanTessellation)
| TEST (PathTest, FanTessellationUnclosedPath)
| TEST (PathTest, StripTessellationUnclosedPath)
| TEST (PathTest, FanTessellationMultiContour)
| TEST (PathTest, StripTessellation)
| TEST (PathTest, StripTessellationMultiContour)
| 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, RectFromIRect)
| 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 (RoundRectTest, RoundingRadiiEmptyDeclaration)
| TEST (RoundRectTest, RoundingRadiiDefaultConstructor)
| TEST (RoundRectTest, RoundingRadiiScalarConstructor)
| TEST (RoundRectTest, RoundingRadiiEmptyScalarConstructor)
| TEST (RoundRectTest, RoundingRadiiSizeConstructor)
| TEST (RoundRectTest, RoundingRadiiEmptySizeConstructor)
| TEST (RoundRectTest, RoundingRadiiNamedSizesConstructor)
| TEST (RoundRectTest, RoundingRadiiPartialNamedSizesConstructor)
| TEST (RoundRectTest, RoundingRadiiMultiply)
| TEST (RoundRectTest, RoundingRadiiEquals)
| TEST (RoundRectTest, RoundingRadiiNotEquals)
| TEST (RoundRectTest, RoundingRadiiCornersSameTolerance)
| TEST (RoundRectTest, EmptyDeclaration)
| TEST (RoundRectTest, DefaultConstructor)
| TEST (RoundRectTest, EmptyRectConstruction)
| TEST (RoundRectTest, RectConstructor)
| TEST (RoundRectTest, InvertedRectConstruction)
| TEST (RoundRectTest, EmptyOvalConstruction)
| TEST (RoundRectTest, OvalConstructor)
| TEST (RoundRectTest, InvertedOvalConstruction)
| TEST (RoundRectTest, RectRadiusConstructor)
| TEST (RoundRectTest, RectXYConstructor)
| TEST (RoundRectTest, RectSizeConstructor)
| TEST (RoundRectTest, RectRadiiConstructor)
| TEST (RoundRectTest, RectRadiiOverflowWidthConstructor)
| TEST (RoundRectTest, RectRadiiOverflowHeightConstructor)
| TEST (RoundRectTest, Shift)
| TEST (RoundRectTest, ExpandScalar)
| TEST (RoundRectTest, ExpandTwoScalars)
| TEST (RoundRectTest, ExpandFourScalars)
| TEST (RoundRectTest, ContractScalar)
| TEST (RoundRectTest, ContractTwoScalars)
| TEST (RoundRectTest, ContractFourScalars)
| TEST (RoundRectTest, ContractAndRequireRadiiAdjustment)
| TEST (RoundRectTest, NoCornerRoundRectContains)
| TEST (RoundRectTest, TinyCornerRoundRectContains)
| TEST (RoundRectTest, UniformCircularRoundRectContains)
| TEST (RoundRectTest, UniformEllipticalRoundRectContains)
| TEST (RoundRectTest, DifferingCornersRoundRectContains)
| TEST (RSTransformTest, Construction)
| TEST (RSTransformTest, CompareToMatrix)
| 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)
| FML_TEST_CLASS (BufferBindingsGLESTest, BindUniformData)
| TEST (BufferBindingsGLESTest, BindUniformData)
| TEST (DeviceBufferGLESTest, BindUniformData)
| TEST (UniqueHandleGLES, MakeUntracked)
| INSTANTIATE_METAL_PLAYGROUND_SUITE (AllocatorMTLTest)
| TEST_P (AllocatorMTLTest, DebugTraceMemoryStatistics)
| TEST_P (SwapchainTransientsMTLTest, CanAllocateSwapchainTextures)
| 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 (CommandPoolRecyclerVKTest, ExtraCommandBufferAllocationsTriggerTrim)
| 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 (ContextVKTest, EmbedderOverridesUsesInstanceExtensions)
| TEST (ContextVKTest, EmbedderOverrides)
| TEST (ContextVKTest, BatchSubmitCommandBuffersOnArm)
| TEST (ContextVKTest, BatchSubmitCommandBuffersOnNonArm)
| TEST (DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded)
| TEST (DescriptorPoolRecyclerVKTest, MultipleCommandBuffersShareDescriptorPool)
| 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)
bool | CanBatchSubmitTest (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanBatchSubmitCommandBuffers)
bool | CanUsePrimitiveRestartSubmitTest (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanUsePrimitiveRestart)
bool | CanUseMipgeneration (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanGenerateMipMaps)
| TEST (DriverInfoVKTest, DriverParsingMali)
| TEST (DriverInfoVKTest, DriverParsingAdreno)
| TEST (DriverInfoVKTest, DisabledDevices)
| TEST (DriverInfoVKTest, EnabledDevicesMali)
| TEST (DriverInfoVKTest, EnabledDevicesAdreno)
bool | CanUseFramebufferFetch (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanUseFramebufferFetch)
| TEST (DriverInfoVKTest, DisableOldXclipseDriver)
| TEST (DriverInfoVKTest, AllPowerVRDisabled)
| TEST (FenceWaiterVKTest, IgnoresNullFence)
| TEST (FenceWaiterVKTest, IgnoresNullCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
| TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
| TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
| TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
| TEST (FormatsVKTest, DescriptorMapping)
| TEST (PipelineCacheDataVKTest, CanTestHeaderCompatibility)
| TEST (PipelineCacheDataVKTest, CanCreateFromDeviceProperties)
| TEST_P (PipelineCacheDataVKPlaygroundTest, CanPersistAndRetrievePipelineCache)
| TEST_P (PipelineCacheDataVKPlaygroundTest, IntegrityChecksArePerformedOnPersistedData)
| TEST (RenderPassBuilder, CreatesRenderPassWithNoDepthStencil)
| TEST (RenderPassBuilder, RenderPassWithLoadOpUsesCurrentLayout)
| 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)
| TEST_P (BlitPassTest, BlitAcrossDifferentPixelFormatsFails)
| TEST_P (BlitPassTest, BlitAcrossDifferentSampleCountsFails)
| TEST_P (BlitPassTest, BlitPassesForMatchingFormats)
| TEST_P (BlitPassTest, ChecksInvalidSliceParameters)
| TEST_P (BlitPassTest, CanBlitSmallRegionToUninitializedTexture)
| TEST_P (BlitPassTest, ChecksInvalidMipLevelParameter)
| TEST_P (BlitPassTest, CanBlitToHigherTextureMipLevels)
| TEST_P (BlitPassTest, CanResizeTextures)
| TEST_P (BlitPassTest, CanResizeTexturesPlayground)
| 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, 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)
| TEST_P (RendererTest, BindingNullTexturesDoesNotCrash)
| 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 std::shared_ptr< 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< std::optional< 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)
| TEST_P (TypographerTest, TextFrameInitialBoundsArePlaceholder)
| TEST_P (TypographerTest, TextFrameInvalidationWithScale)
| TEST_P (TypographerTest, TextFrameAtlasGenerationTracksState)
| TEST_P (TypographerTest, InvalidAtlasForcesRepopulation)

## 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 AiksTest

Definition at line 27 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 19 of file tiled_texture_contents_unittests.cc.

## ◆ HostBufferTest

using impeller::testing::HostBufferTest = typedef EntityPlayground

Definition at line 24 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 20 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.

## ◆ SwapchainTransientsMTLTest

using impeller::testing::SwapchainTransientsMTLTest = typedef PlaygroundTest

Definition at line 24 of file swapchain_transients_mtl_unittests.mm.

## ◆ TextContentsTest

using impeller::testing::TextContentsTest = typedef PlaygroundTest

Definition at line 20 of file text_contents_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 502 of file aiks_dl_blend_unittests.cc.

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

References impeller::Color::alpha, impeller::Color::Black(), impeller::Color::Blend(), impeller::Color::blue, impeller::Color::CornflowerBlue(), impeller::Color::green, impeller::AiksPlayground::ImGuiBegin(), impeller::Color::LimeGreen(), impeller::Color::red, impeller::Color::White(), impeller::Color::WithAlpha(), and x.

## ◆ CanBatchSubmitTest()

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

Definition at line 70 of file driver_info_vk_unittests.cc.

70 {
71 auto const context =
72 MockVulkanContextBuilder()
73 .SetPhysicalPropertiesCallback(
74 [&driver_name, qc](VkPhysicalDevice device,
75 VkPhysicalDeviceProperties* prop) {
76 if (qc) {
77 prop->vendorID = 0x168C; // Qualcomm
78 } else {
79 prop->vendorID = 0x13B5; // ARM
80 }
81 driver_name.copy(prop->deviceName, driver_name.size());
82 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
83 })
84 .Build();
85 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
86 .batch_submit_command_buffer_timeout;
87 }

References impeller::WorkaroundsVK::batch_submit_command_buffer_timeout, and impeller::GetWorkaroundsFromDriverInfo().

Referenced by TEST().

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

## ◆ CanUseFramebufferFetch()

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

Definition at line 196 of file driver_info_vk_unittests.cc.

196 {
197 auto const context =
198 MockVulkanContextBuilder()
199 .SetPhysicalPropertiesCallback(
200 [&driver_name, qc](VkPhysicalDevice device,
201 VkPhysicalDeviceProperties* prop) {
202 if (qc) {
203 prop->vendorID = 0x168C; // Qualcomm
204 } else {
205 prop->vendorID = 0x13B5; // ARM
206 }
207 driver_name.copy(prop->deviceName, driver_name.size());
208 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
209 })
210 .Build();
211 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
212 .input_attachment_self_dependency_broken;
213 }

References impeller::GetWorkaroundsFromDriverInfo(), and impeller::WorkaroundsVK::input_attachment_self_dependency_broken.

Referenced by TEST().

## ◆ CanUseMipgeneration()

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

Definition at line 126 of file driver_info_vk_unittests.cc.

126 {
127 auto const context =
128 MockVulkanContextBuilder()
129 .SetPhysicalPropertiesCallback(
130 [&driver_name, qc](VkPhysicalDevice device,
131 VkPhysicalDeviceProperties* prop) {
132 if (qc) {
133 prop->vendorID = 0x168C; // Qualcomm
134 } else {
135 prop->vendorID = 0x13B5; // ARM
136 }
137 driver_name.copy(prop->deviceName, driver_name.size());
138 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
139 })
140 .Build();
141 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
142 .broken_mipmap_generation;
143 }

References impeller::WorkaroundsVK::broken_mipmap_generation, and impeller::GetWorkaroundsFromDriverInfo().

Referenced by TEST().

## ◆ CanUsePrimitiveRestartSubmitTest()

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

Definition at line 97 of file driver_info_vk_unittests.cc.

98 {
99 auto const context =
100 MockVulkanContextBuilder()
101 .SetPhysicalPropertiesCallback(
102 [&driver_name, qc](VkPhysicalDevice device,
103 VkPhysicalDeviceProperties* prop) {
104 if (qc) {
105 prop->vendorID = 0x168C; // Qualcomm
106 } else {
107 prop->vendorID = 0x13B5; // ARM
108 }
109 driver_name.copy(prop->deviceName, driver_name.size());
110 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
111 })
112 .Build();
113 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
114 .slow_primitive_restart_performance;
115 }

References impeller::GetWorkaroundsFromDriverInfo(), and impeller::WorkaroundsVK::slow_primitive_restart_performance.

Referenced by TEST().

## ◆ 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 1206 of file renderer_unittests.cc.

1206 {
1207 static CompareFunctionUIData data;
1208 return data;
1209 }

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 1398 of file renderer_unittests.cc.

1399 {
1400 using TexturePipelineBuilder = PipelineBuilder<VertexShader, FragmentShader>;
1401 auto pipeline_desc =
1402 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1403 if (!pipeline_desc.has_value()) {
1404 return nullptr;
1405 }
1406 pipeline_desc->SetSampleCount(SampleCount::kCount4);
1407 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1408 auto pipeline =
1409 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1410 if (!pipeline || !pipeline->IsValid()) {
1411 return nullptr;
1412 }
1413 return pipeline;
1414 }

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::shared_ptr< TextFrame > & | frame
| ) |  |
| static

Definition at line 32 of file typographer_unittests.cc.

39 {
40 frame->SetPerFrameData(scale, {0, 0}, Matrix(), std::nullopt);
41 return typographer_context->CreateGlyphAtlas(context, type, host_buffer,
42 atlas_context, {frame});
43 }

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

Referenced by TEST_P().

## ◆ 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 std::vector< std::shared_ptr< TextFrame >> & | frames,
|  | const std::vector< std::optional< GlyphProperties >> & | properties
| ) |  |
| static

Definition at line 45 of file typographer_unittests.cc.

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

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

## ◆ 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`,
|  | bool | requires_readback = `false`
| ) |  |

Definition at line 24 of file canvas_unittests.cc.

27 {
28 TextureDescriptor onscreen_desc;
29 onscreen_desc.size = {100, 100};
30 onscreen_desc.format =
31 context.GetDeviceCapabilities().GetDefaultColorFormat();
32 onscreen_desc.usage = TextureUsage::kRenderTarget;
33 onscreen_desc.storage_mode = StorageMode::kDevicePrivate;
34 onscreen_desc.sample_count = SampleCount::kCount1;
35 std::shared_ptr<Texture> onscreen =
36 context.GetContext()->GetResourceAllocator()->CreateTexture(
37 onscreen_desc);
38
39 ColorAttachment color0;
40 color0.load_action = LoadAction::kClear;
41 if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
42 TextureDescriptor onscreen_msaa_desc = onscreen_desc;
43 onscreen_msaa_desc.sample_count = SampleCount::kCount4;
44 onscreen_msaa_desc.storage_mode = StorageMode::kDeviceTransient;
45 onscreen_msaa_desc.type = TextureType::kTexture2DMultisample;
46
47 std::shared_ptr<Texture> onscreen_msaa =
48 context.GetContext()->GetResourceAllocator()->CreateTexture(
49 onscreen_msaa_desc);
50 color0.resolve_texture = onscreen;
51 color0.texture = onscreen_msaa;
52 color0.store_action = StoreAction::kMultisampleResolve;
53 } else {
54 color0.texture = onscreen;
55 }
56
57 RenderTarget render_target;
58 render_target.SetColorAttachment(color0, 0);
59
60 if (cull_rect.has_value()) {
61 return std::make_unique<Canvas>(
62 context, render_target, /*is_onscreen=*/false,
63 /*requires_readback=*/requires_readback, cull_rect.value());
64 }
65 return std::make_unique<Canvas>(context, render_target, /*is_onscreen=*/false,
66 /*requires_readback=*/requires_readback);
67 }

References impeller::TextureDescriptor::format, impeller::ContentContext::GetContext(), impeller::Capabilities::GetDefaultColorFormat(), impeller::ContentContext::GetDeviceCapabilities(), impeller::kClear, impeller::kCount1, impeller::kCount4, impeller::kDevicePrivate, impeller::kDeviceTransient, impeller::kMultisampleResolve, impeller::kRenderTarget, impeller::kTexture2DMultisample, impeller::Attachment::load_action, impeller::Attachment::resolve_texture, impeller::TextureDescriptor::sample_count, impeller::RenderTarget::SetColorAttachment(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, impeller::TextureDescriptor::type, and impeller::TextureDescriptor::usage.

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

1598 {
1599 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
1600 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
1601 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
1602 Vector3 white = {1.0, 1.0, 1.0};
1603 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
1604 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
1605 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
1606 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
1607 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
1608 std::vector<uint8_t> y_data;
1609 std::vector<uint8_t> uv_data;
1610 for (int i = 0; i < 4; i++) {
1611 auto yuv = yuvs[i];
1612 uint8_t y = std::round(yuv.x * 255.0);
1613 uint8_t u = std::round(yuv.y * 255.0);
1614 uint8_t v = std::round(yuv.z * 255.0);
1615 for (int j = 0; j < 16; j++) {
1616 y_data.push_back(y);
1617 }
1618 for (int j = 0; j < 8; j++) {
1619 uv_data.push_back(j % 2 == 0 ? u : v);
1620 }
1621 }
1622 auto cmd_buffer = context->CreateCommandBuffer();
1623 auto blit_pass = cmd_buffer->CreateBlitPass();
1624
1625 impeller::TextureDescriptor y_texture_descriptor;
1626 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1627 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
1628 y_texture_descriptor.size = {8, 8};
1629 auto y_texture =
1630 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
1631 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
1632 auto y_mapping_buffer =
1633 context->GetResourceAllocator()->CreateBufferWithCopy(*y_mapping);
1634
1635 blit_pass->AddCopy(DeviceBuffer::AsBufferView(y_mapping_buffer), y_texture);
1636
1637 impeller::TextureDescriptor uv_texture_descriptor;
1638 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1639 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
1640 uv_texture_descriptor.size = {4, 4};
1641 auto uv_texture =
1642 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
1643 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
1644 auto uv_mapping_buffer =
1645 context->GetResourceAllocator()->CreateBufferWithCopy(*uv_mapping);
1646
1647 blit_pass->AddCopy(DeviceBuffer::AsBufferView(uv_mapping_buffer), uv_texture);
1648
1649 if (!blit_pass->EncodeCommands() ||
1650 !context->GetCommandQueue()->Submit({cmd_buffer}).ok()) {
1651 FML_DLOG(ERROR) << "Could not copy contents into Y/UV texture.";
1652 }
1653
1654 return {y_texture, uv_texture};
1655 }

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(SkPoint{100, 0}, SkPoint{100, 60}, line_paint);
92 builder.DrawLine(SkPoint{0, 30}, SkPoint{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 | ) |
| inline static constexpr

Definition at line 1324 of file rect_unittests.cc.

1324 {
1325 return R::MakeLTRB(rect.GetRight(), rect.GetTop(), //
1326 rect.GetLeft(), rect.GetBottom());
1327 }

Referenced by flip_lrtb(), and TEST().

## ◆ flip_lrtb()

template<typename R >

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

Definition at line 1336 of file rect_unittests.cc.

1336 {
1337 return flip_lr(flip_tb(rect));
1338 }

References flip_lr(), and flip_tb().

Referenced by TEST().

## ◆ flip_tb()

template<typename R >

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

Definition at line 1330 of file rect_unittests.cc.

1330 {
1331 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(), //
1332 rect.GetRight(), rect.GetTop());
1333 }

Referenced by flip_lrtb(), and TEST().

## ◆ FML_TEST_CLASS()

impeller::testing::FML_TEST_CLASS | ( | BufferBindingsGLESTest | ,
|  | BindUniformData |
| ) |  |

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [4/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [5/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [6/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [7/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [8/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [9/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | TextContentsTest |  | ) |

## ◆ 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 506 of file aiks_dl_blur_unittests.cc.

508 {
509 DisplayListBuilder builder;
510 builder.Scale(test_context.GetContentScale().x,
511 test_context.GetContentScale().y);
512 builder.Scale(0.8f, 0.8f);
513 builder.Translate(50.f, 50.f);
514
515 DlPaint draw_paint;
516 draw_paint.setColor(
517 DlColor::RGBA(Color::AntiqueWhite().red, Color::AntiqueWhite().green,
518 Color::AntiqueWhite().blue, Color::AntiqueWhite().alpha));
519 builder.DrawPaint(draw_paint);
520
521 DlPaint paint;
522 paint.setMaskFilter(DlBlurMaskFilter::Make(config.style, config.sigma));
523 paint.setInvertColors(config.invert_colors);
524 paint.setImageFilter(config.image_filter);
525 paint.setBlendMode(config.blend_mode);
526
527 const Scalar x = 50;
528 const Scalar radius = 20.0f;
529 const Scalar y_spacing = 100.0f;
530 Scalar alpha = config.alpha * 255;
531
532 Scalar y = 50;
533 paint.setColor(DlColor::kCrimson().withAlpha(alpha));
534 builder.DrawRect(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
535 radius, 60.0f - radius),
536 paint);
537
538 y += y_spacing;
539 paint.setColor(DlColor::kBlue().withAlpha(alpha));
540 builder.DrawCircle(SkPoint{x + 25, y + 25}, radius, paint);
541
542 y += y_spacing;
543 paint.setColor(DlColor::kGreen().withAlpha(alpha));
544 builder.DrawOval(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
545 radius, 60.0f - radius),
546 paint);
547
548 y += y_spacing;
549 paint.setColor(DlColor::kPurple().withAlpha(alpha));
550 SkRRect rrect =
551 SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, radius);
552 builder.DrawRRect(rrect, paint);
553
554 y += y_spacing;
555 paint.setColor(DlColor::kOrange().withAlpha(alpha));
556
557 rrect =
558 SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, 5.0);
559 builder.DrawRRect(rrect, paint);
560
561 y += y_spacing;
562 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
563
564 {
565 SkPath path;
566 path.moveTo(x + 0, y + 60);
567 path.lineTo(x + 30, y + 0);
568 path.lineTo(x + 60, y + 60);
569 path.close();
570
571 builder.DrawPath(path, paint);
572 }
573
574 y += y_spacing;
575 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
576 {
577 SkPath path;
578 path.addArc(SkRect::MakeXYWH(x + 5, y, 50, 50), 90, 180);
579 path.addArc(SkRect::MakeXYWH(x + 25, y, 50, 50), 90, 180);
580 path.close();
581 builder.DrawPath(path, paint);
582 }
583
584 return builder.Build();
585 }

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, 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 39 of file aiks_dl_text_unittests.cc.

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

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

## ◆ RGBToYUV()

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

Definition at line 1579 of file entity_unittests.cc.

1579 {
1580 Vector3 yuv;
1581 switch (yuv_color_space) {
1582 case YUVColorSpace::kBT601FullRange:
1583 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
1584 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
1585 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
1586 break;
1587 case YUVColorSpace::kBT601LimitedRange:
1588 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
1589 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
1590 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
1591 break;
1592 }
1593 return yuv;
1594 }

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

Referenced by CreateTestYUVTextures().

## ◆ swap_nan() [1/2]

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

Definition at line 1350 of file rect_unittests.cc.

1350 {
1351 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1352 FML_DCHECK(index >= 0 && index <= 3);
1353 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.x;
1354 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.y;
1355 return Point(x, y);
1356 }

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

## ◆ swap_nan() [2/2]

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

Definition at line 1340 of file rect_unittests.cc.

1340 {
1341 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1342 FML_DCHECK(index >= 0 && index <= 15);
1343 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.GetLeft();
1344 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.GetTop();
1345 Scalar r = ((index & (1 << 2)) != 0) ? nan : rect.GetRight();
1346 Scalar b = ((index & (1 << 3)) != 0) ? nan : rect.GetBottom();
1347 return Rect::MakeLTRB(l, t, r, b);
1348 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 38 of file allocator_vk_unittests.cc.

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

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [13/465]

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

Definition at line 53 of file allocator_vk_unittests.cc.

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

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [14/465]

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

Definition at line 19 of file allocator_vk_unittests.cc.

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

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

## ◆ TEST() [15/465]

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, impeller::kBaz, and x.

## ◆ TEST() [16/465]

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

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

impeller::testing::TEST | ( | BufferBindingsGLESTest | ,
|  | BindUniformData |
| ) |  |

Definition at line 17 of file buffer_bindings_gles_unittests.cc.

17 {
18 BufferBindingsGLES bindings;
19 absl::flat_hash_map<std::string, GLint> uniform_bindings;
20 uniform_bindings["SHADERMETADATA.FOOBAR"] = 1;
21 bindings.SetUniformBindings(std::move(uniform_bindings));
22 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
23
24 EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
25
26 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
27 std::vector<BufferResource> bound_buffers;
28 std::vector<TextureAndSampler> bound_textures;
29
30 ShaderMetadata shader_metadata = {
31 .name = "shader_metadata",
32 .members = {ShaderStructMemberMetadata{.type = ShaderType::kFloat,
33 .name = "foobar",
34 .offset = 0,
35 .size = sizeof(float),
36 .byte_length = sizeof(float)}}};
37 std::shared_ptr<ReactorGLES> reactor;
38 std::shared_ptr<Allocation> backing_store = std::make_shared<Allocation>();
39 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float)}));
40 DeviceBufferGLES device_buffer(DeviceBufferDescriptor{.size = sizeof(float)},
41 reactor, backing_store);
42 BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
43 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
44
45 EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
46 bound_buffers, Range{0, 0},
47 Range{0, 1}));
48 }

References impeller::BufferBindingsGLES::BindUniformData(), buffer_view, impeller::kFloat, impeller::ShaderMetadata::name, impeller::DeviceBufferDescriptor::size, and impeller::ShaderStructMemberMetadata::type.

## ◆ TEST() [19/465]

impeller::testing::TEST | ( | BufferViewTest | ,
|  | Empty |
| ) |  |

Definition at line 11 of file buffer_view_unittests.cc.

11 {
12 BufferView buffer_view;
13 EXPECT_FALSE(buffer_view);
14 }

References buffer_view.

## ◆ TEST() [20/465]

impeller::testing::TEST | ( | BufferViewTest | ,
|  | TakeRaw |
| ) |  |

Definition at line 16 of file buffer_view_unittests.cc.

16 {
17 DeviceBuffer* buffer = reinterpret_cast<DeviceBuffer*>(0xcafebabe);
18 BufferView buffer_view(buffer, {0, 123});
19 EXPECT_TRUE(buffer_view);
20 std::shared_ptr<const DeviceBuffer> taken = buffer_view.TakeBuffer();
21 EXPECT_FALSE(taken);
22 EXPECT_EQ(buffer_view.GetBuffer(), buffer);
23 }

References buffer_view.

## ◆ TEST() [21/465]

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() [22/465]

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() [23/465]

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() [24/465]

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() [25/465]

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() [26/465]

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

Definition at line 215 of file context_vk_unittests.cc.

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

## ◆ TEST() [27/465]

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

Definition at line 184 of file context_vk_unittests.cc.

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

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

## ◆ TEST() [28/465]

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

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

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

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

Definition at line 165 of file command_pool_vk_unittests.cc.

165 {
166 auto const context = MockVulkanContextBuilder().Build();
167
168 {
169 // Fetch a pool (which will be created).
170 auto const recycler = context->GetCommandPoolRecycler();
171 auto pool = recycler->Get();
172
173 // Allocate a large number of command buffers
174 for (auto i = 0; i < 64; i++) {
175 auto buffer = pool->CreateCommandBuffer();
176 pool->CollectCommandBuffer(std::move(buffer));
177 }
178
179 // This normally is called at the end of a frame.
180 recycler->Dispose();
181 }
182
183 // Wait for the pool to be reclaimed.
184 for (auto i = 0u; i < 2u; i++) {
185 auto waiter = fml::AutoResetWaitableEvent();
186 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
187 {
188 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
189 std::move(rattle));
190 }
191 waiter.Wait();
192 }
193
194 // Command pool is reset but does not release resources.
195 auto called = GetMockVulkanFunctions(context->GetDevice());
196 EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetCommandPool"),
197 1u);
198
199 // Create the pool a second time, but dont use any command buffers.
200 {
201 // Fetch a pool (which will be created).
202 auto const recycler = context->GetCommandPoolRecycler();
203 auto pool = recycler->Get();
204
205 // This normally is called at the end of a frame.
206 recycler->Dispose();
207 }
208
209 // Wait for the pool to be reclaimed.
210 for (auto i = 0u; i < 2u; i++) {
211 auto waiter = fml::AutoResetWaitableEvent();
212 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
213 {
214 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
215 std::move(rattle));
216 }
217 waiter.Wait();
218 }
219
220 // Verify that the cmd pool was trimmed.
221
222 // Now check that we only ever created one pool and one command buffer.
223 called = GetMockVulkanFunctions(context->GetDevice());
224 EXPECT_EQ(std::count(called->begin(), called->end(),
225 "vkResetCommandPoolReleaseResources"),
226 1u);
227
228 context->Shutdown();
229 }

## ◆ TEST() [32/465]

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() [33/465]

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() [34/465]

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() [35/465]

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() [36/465]

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() [37/465]

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() [38/465]

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

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() [40/465]

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

Definition at line 306 of file context_vk_unittests.cc.

306 {
307 std::shared_ptr<ContextVK> context =
308 MockVulkanContextBuilder()
309 .SetPhysicalPropertiesCallback(
310 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
311 prop->vendorID = 0x13B5; // ARM
312 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
313 })
314 .Build();
315
316 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
317 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
318
319 // If command buffers are batch submitted, we should have created them but not
320 // created the fence to track them after enqueing.
321 auto functions = GetMockVulkanFunctions(context->GetDevice());
322 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
323 "vkAllocateCommandBuffers") != functions->end());
324 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
325 "vkCreateFence") == functions->end());
326
327 context->FlushCommandBuffers();
328
329 // After flushing, the fence should be created.
330 functions = GetMockVulkanFunctions(context->GetDevice());
331 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
332 "vkCreateFence") != functions->end());
333 }

## ◆ TEST() [41/465]

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

Definition at line 335 of file context_vk_unittests.cc.

335 {
336 std::shared_ptr<ContextVK> context =
337 MockVulkanContextBuilder()
338 .SetPhysicalPropertiesCallback(
339 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
340 prop->vendorID = 0x8686; // Made up ID
341 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
342 })
343 .Build();
344
345 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
346 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
347
348 // If command buffers are batch not submitted, we should have created them and
349 // a corresponding fence immediately.
350 auto functions = GetMockVulkanFunctions(context->GetDevice());
351 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
352 "vkAllocateCommandBuffers") != functions->end());
353 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
354 "vkCreateFence") != functions->end());
355 }

## ◆ TEST() [42/465]

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

Definition at line 152 of file context_vk_unittests.cc.

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

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [43/465]

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

Definition at line 166 of file context_vk_unittests.cc.

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

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [44/465]

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

Definition at line 17 of file context_vk_unittests.cc.

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

References impeller::ContextVK::ChooseThreadCountForWorkers().

## ◆ TEST() [45/465]

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

Definition at line 95 of file context_vk_unittests.cc.

95 {
96 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
97 std::shared_ptr<std::vector<std::string>> functions;
98 {
99 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
100 PipelineDescriptor pipeline_desc;
101 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
102 PipelineFuture<PipelineDescriptor> pipeline_future =
103 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
104 pipeline = pipeline_future.Get();
105 ASSERT_TRUE(pipeline);
106 functions = GetMockVulkanFunctions(context->GetDevice());
107 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
108 "vkCreateGraphicsPipelines") != functions->end());
109 }
110 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
111 "vkDestroyDevice") != functions->end());
112 }

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

## ◆ TEST() [46/465]

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

Definition at line 136 of file context_vk_unittests.cc.

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

References impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [47/465]

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

Definition at line 30 of file context_vk_unittests.cc.

30 {
31 std::weak_ptr<ContextVK> weak_context;
32 std::weak_ptr<CommandPoolVK> weak_pool;
33 {
34 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
35 auto const pool = context->GetCommandPoolRecycler()->Get();
36 weak_pool = pool;
37 weak_context = context;
38 ASSERT_TRUE(weak_pool.lock());
39 ASSERT_TRUE(weak_context.lock());
40 }
41 ASSERT_FALSE(weak_pool.lock());
42 ASSERT_FALSE(weak_context.lock());
43 }

## ◆ TEST() [48/465]

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

Definition at line 45 of file context_vk_unittests.cc.

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

## ◆ TEST() [49/465]

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

Definition at line 114 of file context_vk_unittests.cc.

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

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

## ◆ TEST() [50/465]

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

Definition at line 283 of file context_vk_unittests.cc.

283 {
284 ContextVK::EmbedderData data;
285 auto other_context = MockVulkanContextBuilder().Build();
286
287 data.instance = other_context->GetInstance();
288 data.device = other_context->GetDevice();
289 data.physical_device = other_context->GetPhysicalDevice();
290 data.queue = VkQueue{};
291 data.queue_family_index = 0;
292 data.instance_extensions = {"VK_KHR_surface",
293 "VK_KHR_portability_enumeration"};
294 data.device_extensions = {"VK_KHR_swapchain"};
295
296 auto context = MockVulkanContextBuilder().SetEmbedderData(data).Build();
297
298 EXPECT_TRUE(context->IsValid());
299 EXPECT_EQ(context->GetInstance(), other_context->GetInstance());
300 EXPECT_EQ(context->GetDevice(), other_context->GetDevice());
301 EXPECT_EQ(context->GetPhysicalDevice(), other_context->GetPhysicalDevice());
302 EXPECT_EQ(context->GetGraphicsQueue()->GetIndex().index, 0u);
303 EXPECT_EQ(context->GetGraphicsQueue()->GetIndex().family, 0u);
304 }

References data.

## ◆ TEST() [51/465]

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

Definition at line 264 of file context_vk_unittests.cc.

264 {
265 ContextVK::EmbedderData data;
266 auto other_context = MockVulkanContextBuilder().Build();
267
268 data.instance = other_context->GetInstance();
269 data.device = other_context->GetDevice();
270 data.physical_device = other_context->GetPhysicalDevice();
271 data.queue = VkQueue{};
272 data.queue_family_index = 0;
273 // Missing surface extension.
274 data.instance_extensions = {};
275 data.device_extensions = {"VK_KHR_swapchain"};
276
277 ScopedValidationDisable scoped;
278 auto context = MockVulkanContextBuilder().SetEmbedderData(data).Build();
279
280 EXPECT_EQ(context, nullptr);
281 }

References data.

## ◆ TEST() [52/465]

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

Definition at line 245 of file context_vk_unittests.cc.

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

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

## ◆ TEST() [53/465]

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

Definition at line 256 of file context_vk_unittests.cc.

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

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

## ◆ TEST() [54/465]

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

Definition at line 76 of file context_vk_unittests.cc.

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

## ◆ TEST() [55/465]

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

Definition at line 234 of file context_vk_unittests.cc.

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

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST() [56/465]

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

Definition at line 16 of file descriptor_pool_vk_unittests.cc.

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

## ◆ TEST() [57/465]

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

Definition at line 127 of file descriptor_pool_vk_unittests.cc.

127 {
128 auto const context = MockVulkanContextBuilder().Build();
129
130 auto cmd_buffer_1 = context->CreateCommandBuffer();
131 auto cmd_buffer_2 = context->CreateCommandBuffer();
132
133 CommandBufferVK& vk_1 = CommandBufferVK::Cast(*cmd_buffer_1);
134 CommandBufferVK& vk_2 = CommandBufferVK::Cast(*cmd_buffer_2);
135
136 EXPECT_EQ(&vk_1.GetDescriptorPool(), &vk_2.GetDescriptorPool());
137
138 // Resetting resources creates a new pool.
139 context->DisposeThreadLocalCachedResources();
140
141 auto cmd_buffer_3 = context->CreateCommandBuffer();
142 CommandBufferVK& vk_3 = CommandBufferVK::Cast(*cmd_buffer_3);
143
144 EXPECT_NE(&vk_1.GetDescriptorPool(), &vk_3.GetDescriptorPool());
145
146 context->Shutdown();
147 }

References impeller::BackendCast< CommandBufferVK, CommandBuffer >::Cast(), and impeller::CommandBufferVK::GetDescriptorPool().

## ◆ TEST() [58/465]

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

Definition at line 66 of file descriptor_pool_vk_unittests.cc.

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

## ◆ TEST() [59/465]

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

Definition at line 28 of file descriptor_pool_vk_unittests.cc.

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

## ◆ TEST() [60/465]

impeller::testing::TEST | ( | DeviceBufferGLESTest | ,
|  | BindUniformData |
| ) |  |

Definition at line 25 of file device_buffer_gles_unittests.cc.

25 {
26 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
27
28 EXPECT_CALL(*mock_gles_impl, GenBuffers(1, _)).Times(1);
29
30 std::shared_ptr<MockGLES> mock_gled =
31 MockGLES::Init(std::move(mock_gles_impl));
32 ProcTableGLES::Resolver resolver = kMockResolverGLES;
33 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
34 auto worker = std::make_shared<TestWorker>();
35 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
36 reactor->AddWorker(worker);
37
38 std::shared_ptr<Allocation> backing_store = std::make_shared<Allocation>();
39 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float)}));
40 DeviceBufferGLES device_buffer(DeviceBufferDescriptor{.size = sizeof(float)},
41 reactor, backing_store);
42 EXPECT_FALSE(device_buffer.GetHandle().has_value());
43 EXPECT_TRUE(device_buffer.BindAndUploadDataIfNecessary(
44 DeviceBufferGLES::BindingType::kUniformBuffer));
45 EXPECT_TRUE(device_buffer.GetHandle().has_value());
46 }

References impeller::DeviceBufferGLES::kUniformBuffer, and impeller::DeviceBufferDescriptor::size.

## ◆ TEST() [61/465]

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() [62/465]

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

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

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

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

Definition at line 253 of file driver_info_vk_unittests.cc.

253 {
254 auto const context =
255 MockVulkanContextBuilder()
256 .SetPhysicalPropertiesCallback(
257 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
258 prop->vendorID = 0x1010;
259 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
260 })
261 .Build();
262
263 EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver());
264 }

## ◆ TEST() [66/465]

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

Definition at line 89 of file driver_info_vk_unittests.cc.

89 {
90 // Old Adreno no batch submit!
91 EXPECT_FALSE(CanBatchSubmitTest("Adreno (TM) 540", true));
92
93 EXPECT_TRUE(CanBatchSubmitTest("Mali-G51", false));
94 EXPECT_TRUE(CanBatchSubmitTest("Adreno (TM) 750", true));
95 }

References CanBatchSubmitTest().

## ◆ TEST() [67/465]

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

Definition at line 145 of file driver_info_vk_unittests.cc.

145 {
146 // Adreno no mips
147 EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 540", true));
148 EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 750", true));
149
150 // Mali A-OK
151 EXPECT_TRUE(CanUseMipgeneration("Mali-G51", false));
152 }

References CanUseMipgeneration().

## ◆ TEST() [68/465]

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

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

Definition at line 215 of file driver_info_vk_unittests.cc.

215 {
216 // Adreno no primitive restart on models as or older than 630.
217 EXPECT_FALSE(CanUseFramebufferFetch("Adreno (TM) 540", true));
218 EXPECT_FALSE(CanUseFramebufferFetch("Adreno (TM) 630", true));
219
220 EXPECT_TRUE(CanUseFramebufferFetch("Adreno (TM) 640", true));
221 EXPECT_TRUE(CanUseFramebufferFetch("Adreno (TM) 750", true));
222 EXPECT_TRUE(CanUseFramebufferFetch("Mali-G51", false));
223 }

References CanUseFramebufferFetch().

## ◆ TEST() [70/465]

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

Definition at line 117 of file driver_info_vk_unittests.cc.

117 {
118 // Adreno no primitive restart
119 EXPECT_FALSE(CanUsePrimitiveRestartSubmitTest("Adreno (TM) 540", true));
120 EXPECT_FALSE(CanUsePrimitiveRestartSubmitTest("Adreno (TM) 750", true));
121
122 // Mali A-OK
123 EXPECT_TRUE(CanUsePrimitiveRestartSubmitTest("Mali-G51", false));
124 }

References CanUsePrimitiveRestartSubmitTest().

## ◆ TEST() [71/465]

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

Definition at line 165 of file driver_info_vk_unittests.cc.

165 {
166 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 620"));
167 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 610"));
168 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 530"));
169 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 512"));
170 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 509"));
171 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 508"));
172 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 506"));
173 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 505"));
174 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 504"));
175 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 630"));
176 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 640"));
177 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 650"));
178 }

References IsBadVersionTest().

## ◆ TEST() [72/465]

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

Definition at line 225 of file driver_info_vk_unittests.cc.

225 {
226 auto context =
227 MockVulkanContextBuilder()
228 .SetPhysicalPropertiesCallback(
229 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
230 prop->vendorID = 0x144D; // Samsung
231 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
232 // Version 1.1.0
233 prop->apiVersion = (1 << 22) | (1 << 12);
234 })
235 .Build();
236
237 EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver());
238
239 context =
240 MockVulkanContextBuilder()
241 .SetPhysicalPropertiesCallback(
242 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
243 prop->vendorID = 0x144D; // Samsung
244 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
245 // Version 1.3.0
246 prop->apiVersion = (1 << 22) | (3 << 12);
247 })
248 .Build();
249
250 EXPECT_FALSE(context->GetDriverInfo()->IsKnownBadDriver());
251 }

## ◆ TEST() [73/465]

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

Definition at line 160 of file driver_info_vk_unittests.cc.

160 {
161 EXPECT_EQ(GetAdrenoVersion("Adreno (TM) 540"), AdrenoGPU::kAdreno540);
162 EXPECT_EQ(GetAdrenoVersion("Foo Bar"), AdrenoGPU::kUnknown);
163 }

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

## ◆ TEST() [74/465]

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

Definition at line 154 of file driver_info_vk_unittests.cc.

154 {
155 EXPECT_EQ(GetMaliVersion("Mali-G51-MORE STUFF"), MaliGPU::kG51);
156 EXPECT_EQ(GetMaliVersion("Mali-G51"), MaliGPU::kG51);
157 EXPECT_EQ(GetMaliVersion("Mali-111111"), MaliGPU::kUnknown);
158 }

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

## ◆ TEST() [75/465]

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

Definition at line 185 of file driver_info_vk_unittests.cc.

185 {
186 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 750"));
187 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 740"));
188 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 732"));
189 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 730"));
190 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 725"));
191 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 720"));
192 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 710"));
193 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 702"));
194 }

References IsBadVersionTest().

## ◆ TEST() [76/465]

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

Definition at line 180 of file driver_info_vk_unittests.cc.

180 {
181 EXPECT_FALSE(IsBadVersionTest("Mali-G52", /*qc=*/false));
182 EXPECT_FALSE(IsBadVersionTest("Mali-G54-MORE STUFF", /*qc=*/false));
183 }

References IsBadVersionTest().

## ◆ TEST() [77/465]

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

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

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

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

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

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

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

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

Definition at line 58 of file clip_stack_unittests.cc.

58 {
59 EntityPassClipStack recorder =
60 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
61
62 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
63
64 // Push a clip.
65 EntityPassClipStack::ClipStateResult result =
66 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.5, 55.5),
67 /*is_axis_aligned_rect=*/true),
68 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
69 EXPECT_TRUE(result.should_render);
70 EXPECT_TRUE(result.clip_did_change);
71
72 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
73 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
74 Rect::MakeLTRB(50, 50, 55.5, 55.5));
75 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
76 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
77
78 // Restore the clip.
79 recorder.RecordRestore({0, 0}, 0);
80
81 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
82 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
83 Rect::MakeSize(Size::MakeWH(100, 100)));
84 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
85 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
86 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::RecordClip(), impeller::EntityPassClipStack::RecordRestore(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [85/465]

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

Definition at line 88 of file clip_stack_unittests.cc.

88 {
89 EntityPassClipStack recorder =
90 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
91
92 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
93
94 // Push a clip.
95 EntityPassClipStack::ClipStateResult result =
96 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.4, 55.4),
97 /*is_axis_aligned_rect=*/true),
98 Matrix(), {0, 0}, 0, 100, /*is_aa=*/false);
99 EXPECT_FALSE(result.should_render);
100 EXPECT_TRUE(result.clip_did_change);
101
102 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
103 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
104 Rect::MakeLTRB(50, 50, 55, 55));
105 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
106 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
107
108 // Restore the clip.
109 recorder.RecordRestore({0, 0}, 0);
110
111 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
112 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
113 Rect::MakeSize(Size::MakeWH(100, 100)));
114 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
115 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
116 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::RecordClip(), impeller::EntityPassClipStack::RecordRestore(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [86/465]

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

Definition at line 171 of file clip_stack_unittests.cc.

171 {
172 EntityPassClipStack recorder =
173 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
174
175 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
176
177 // Push Clips that shrink in size. All should be applied.
178 Entity entity;
179
180 for (auto i = 1; i < 20; i++) {
181 EntityPassClipStack::ClipStateResult result = recorder.RecordClip(
182 ClipContents(Rect::MakeLTRB(i, i, 99.6 - i, 99.6 - i),
183 /*is_axis_aligned_rect=*/true),
184 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
185
186 EXPECT_TRUE(result.should_render);
187 EXPECT_TRUE(result.clip_did_change);
188 EXPECT_EQ(recorder.CurrentClipCoverage(),
189 Rect::MakeLTRB(i, i, 99.6 - i, 99.6 - i));
190 }
191 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::CurrentClipCoverage(), impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [87/465]

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

Definition at line 193 of file clip_stack_unittests.cc.

193 {
194 EntityPassClipStack recorder =
195 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
196
197 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
198
199 // Push Clips that grow in size. All should be skipped.
200
201 for (auto i = 1; i < 20; i++) {
202 EntityPassClipStack::ClipStateResult result = recorder.RecordClip(
203 ClipContents(Rect::MakeLTRB(0 - i, 0 - i, 100 + i, 100 + i),
204 /*is_axis_aligned_rect=*/true),
205 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
206
207 EXPECT_FALSE(result.should_render);
208 EXPECT_FALSE(result.clip_did_change);
209 EXPECT_EQ(recorder.CurrentClipCoverage(), Rect::MakeLTRB(0, 0, 100, 100));
210 }
211 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::CurrentClipCoverage(), impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [88/465]

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

Definition at line 120 of file clip_stack_unittests.cc.

120 {
121 EntityPassClipStack recorder =
122 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
123
124 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
125
126 // Push a clip.
127 EntityPassClipStack::ClipStateResult result =
128 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.5, 55.5),
129 /*is_axis_aligned_rect=*/true),
130 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
131
132 EXPECT_TRUE(result.should_render);
133 EXPECT_TRUE(result.clip_did_change);
134
135 // Push a clip with larger coverage than the previous state.
136 result = recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 100.5, 100.5),
137 /*is_axis_aligned_rect=*/true),
138 Matrix(), {0, 0}, 1, 100, /*is_aa=*/true);
139
140 EXPECT_FALSE(result.should_render);
141 EXPECT_FALSE(result.clip_did_change);
142 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [89/465]

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

Definition at line 146 of file clip_stack_unittests.cc.

147 {
148 EntityPassClipStack recorder =
149 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
150
151 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
152
153 // Push a clip.
154 EntityPassClipStack::ClipStateResult result =
155 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55, 55),
156 /*is_axis_aligned_rect=*/true),
157 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
158
159 EXPECT_FALSE(result.should_render);
160 EXPECT_TRUE(result.clip_did_change);
161
162 // Push a clip with larger coverage than the previous state.
163 result = recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 100, 100),
164 /*is_axis_aligned_rect=*/false),
165 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
166
167 EXPECT_TRUE(result.should_render);
168 EXPECT_TRUE(result.clip_did_change);
169 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [90/465]

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

Definition at line 48 of file clip_stack_unittests.cc.

48 {
49 EntityPassClipStack recorder =
50 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
51
52 EXPECT_TRUE(recorder.GetReplayEntities().empty());
53
54 recorder.RecordRestore({0, 0}, 0);
55 EXPECT_TRUE(recorder.GetReplayEntities().empty());
56 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordRestore().

## ◆ TEST() [91/465]

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

Definition at line 14 of file clip_stack_unittests.cc.

14 {
15 EntityPassClipStack recorder =
16 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
17
18 EXPECT_TRUE(recorder.GetReplayEntities().empty());
19
20 recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 100, 100),
21 /*is_axis_aligned_rect=*/false),
22 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
23
24 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
25
26 recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 50.5, 50.5),
27 /*is_axis_aligned_rect=*/true),
28 Matrix(), {0, 0}, 2, 100, /*is_aa=*/true);
29
30 EXPECT_EQ(recorder.GetReplayEntities().size(), 2u);
31 ASSERT_TRUE(recorder.GetReplayEntities()[0].clip_coverage.has_value());
32 ASSERT_TRUE(recorder.GetReplayEntities()[1].clip_coverage.has_value());
33
34 // NOLINTBEGIN(bugprone-unchecked-optional-access)
35 EXPECT_EQ(recorder.GetReplayEntities()[0].clip_coverage.value(),
36 Rect::MakeLTRB(0, 0, 100, 100));
37 EXPECT_EQ(recorder.GetReplayEntities()[1].clip_coverage.value(),
38 Rect::MakeLTRB(0, 0, 50.5, 50.5));
39 // NOLINTEND(bugprone-unchecked-optional-access)
40
41 recorder.RecordRestore({0, 0}, 1);
42 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
43
44 recorder.RecordRestore({0, 0}, 0);
45 EXPECT_TRUE(recorder.GetReplayEntities().empty());
46 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::RecordRestore().

## ◆ TEST() [92/465]

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

Definition at line 232 of file clip_stack_unittests.cc.

232 {
233 EntityPassClipStack recorder =
234 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
235
236 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
237
238 // Push a clip.
239 {
240 EntityPassClipStack::ClipStateResult result =
241 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.5, 55.5),
242 /*is_axis_aligned_rect=*/true),
243 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
244
245 EXPECT_TRUE(result.should_render);
246 EXPECT_TRUE(result.clip_did_change);
247 }
248
249 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
250 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
251 Rect::MakeLTRB(50, 50, 55.5, 55.5));
252 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
253 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
254
255 // Begin a subpass.
256 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
257 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
258 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
259 Rect::MakeLTRB(50, 50, 55, 55));
260
261 {
262 EntityPassClipStack::ClipStateResult result =
263 recorder.RecordClip(ClipContents(Rect::MakeLTRB(54, 54, 54.5, 54.5),
264 /*is_axis_aligned_rect=*/true),
265 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
266
267 EXPECT_TRUE(result.should_render);
268 EXPECT_TRUE(result.clip_did_change);
269 }
270
271 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
272 Rect::MakeLTRB(54, 54, 54.5, 54.5));
273
274 // End subpass.
275 recorder.PopSubpass();
276
277 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
278 Rect::MakeLTRB(50, 50, 55.5, 55.5));
279 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::PopSubpass(), impeller::EntityPassClipStack::PushSubpass(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [93/465]

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

Definition at line 281 of file clip_stack_unittests.cc.

281 {
282 EntityPassClipStack recorder =
283 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
284
285 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
286
287 // Push a clip.
288 {
289 EntityPassClipStack::ClipStateResult result =
290 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.4, 55.4),
291 /*is_axis_aligned_rect=*/true),
292 Matrix(), {0, 0}, 0, 100, /*is_aa=*/false);
293
294 EXPECT_FALSE(result.should_render);
295 EXPECT_TRUE(result.clip_did_change);
296 }
297
298 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
299 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
300 Rect::MakeLTRB(50, 50, 55.0, 55.0));
301 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
302 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
303
304 // Begin a subpass.
305 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
306 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
307 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
308 Rect::MakeLTRB(50, 50, 55, 55));
309
310 {
311 EntityPassClipStack::ClipStateResult result =
312 recorder.RecordClip(ClipContents(Rect::MakeLTRB(54, 54, 55.4, 55.4),
313 /*is_axis_aligned_rect=*/true),
314 Matrix(), {0, 0}, 0, 100, /*is_aa=*/false);
315
316 EXPECT_FALSE(result.should_render);
317 EXPECT_TRUE(result.clip_did_change);
318 }
319
320 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
321 Rect::MakeLTRB(54, 54, 55.0, 55.0));
322
323 // End subpass.
324 recorder.PopSubpass();
325
326 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
327 Rect::MakeLTRB(50, 50, 55, 55));
328 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::PopSubpass(), impeller::EntityPassClipStack::PushSubpass(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [94/465]

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

Definition at line 213 of file clip_stack_unittests.cc.

213 {
214 EntityPassClipStack recorder =
215 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
216
217 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
218
219 // Restore the clip.
220 EntityPassClipStack::ClipStateResult result =
221 recorder.RecordRestore(Point(0, 0), 0);
222 EXPECT_FALSE(result.should_render);
223 EXPECT_FALSE(result.clip_did_change);
224
225 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
226 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
227 Rect::MakeSize(Size::MakeWH(100, 100)));
228 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
229 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
230 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::RecordRestore(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [95/465]

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 }

References value.

## ◆ TEST() [96/465]

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 }

References value.

## ◆ TEST() [97/465]

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 }

References value.

## ◆ TEST() [98/465]

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 }

References value.

## ◆ TEST() [99/465]

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 }

References value.

## ◆ TEST() [100/465]

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() [101/465]

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 }

References value.

## ◆ TEST() [102/465]

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

Definition at line 15 of file filter_input_unittests.cc.

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

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

## ◆ TEST() [103/465]

impeller::testing::TEST | ( | FormatsVKTest | ,
|  | DescriptorMapping |
| ) |  |

Definition at line 11 of file formats_vk_unittests.cc.

11 {
12 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kSampledImage),
13 vk::DescriptorType::eCombinedImageSampler);
14 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kUniformBuffer),
15 vk::DescriptorType::eUniformBuffer);
16 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kStorageBuffer),
17 vk::DescriptorType::eStorageBuffer);
18 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kImage),
19 vk::DescriptorType::eSampledImage);
20 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kSampler),
21 vk::DescriptorType::eSampler);
22 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kInputAttachment),
23 vk::DescriptorType::eInputAttachment);
24 }

References impeller::kImage, impeller::kInputAttachment, impeller::kSampledImage, impeller::kSampler, impeller::kStorageBuffer, impeller::kUniformBuffer, and impeller::ToVKDescriptorType().

## ◆ TEST() [104/465]

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() [105/465]

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() [106/465]

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() [107/465]

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() [108/465]

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() [109/465]

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() [110/465]

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() [111/465]

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() [112/465]

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() [113/465]

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() [114/465]

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() [115/465]

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

Definition at line 1709 of file geometry_unittests.cc.

1709 {
1710 using BlendT = std::underlying_type_t<BlendMode>;
1711 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLast); i++) {
1712 auto mode = static_cast<BlendMode>(i);
1713 auto result = BlendModeToString(mode);
1714 switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) }
1715 }
1716 }

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

## ◆ TEST() [116/465]

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

Definition at line 1718 of file geometry_unittests.cc.

1718 {
1719 {
1720 auto deg = Degrees{90.0};
1721 Radians rad = deg;
1722 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1723 }
1724 }

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

## ◆ TEST() [117/465]

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() [118/465]

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

Definition at line 580 of file geometry_unittests.cc.

580 {
581 ASSERT_EQ((Size{128, 128}.MipCount()), 6u);
582 ASSERT_EQ((Size{128, 256}.MipCount()), 7u);
583 ASSERT_EQ((Size{128, 130}.MipCount()), 7u);
584 ASSERT_EQ((Size{128, 257}.MipCount()), 8u);
585 ASSERT_EQ((Size{257, 128}.MipCount()), 8u);
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() [119/465]

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() [120/465]

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

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

Definition at line 1276 of file geometry_unittests.cc.

1276 {
1277 {
1278 Vector3 p1(1, 2, 3);
1279 Vector3 p2 = p1 + Vector3(1, 2, 3);
1280 ASSERT_EQ(p2.x, 2u);
1281 ASSERT_EQ(p2.y, 4u);
1282 ASSERT_EQ(p2.z, 6u);
1283 }
1284
1285 {
1286 Vector3 p1(3, 6, 9);
1287 Vector3 p2 = p1 - Vector3(1, 2, 3);
1288 ASSERT_EQ(p2.x, 2u);
1289 ASSERT_EQ(p2.y, 4u);
1290 ASSERT_EQ(p2.z, 6u);
1291 }
1292
1293 {
1294 Vector3 p1(1, 2, 3);
1295 Vector3 p2 = p1 * Vector3(2, 3, 4);
1296 ASSERT_EQ(p2.x, 2u);
1297 ASSERT_EQ(p2.y, 6u);
1298 ASSERT_EQ(p2.z, 12u);
1299 }
1300
1301 {
1302 Vector3 p1(2, 6, 12);
1303 Vector3 p2 = p1 / Vector3(2, 3, 4);
1304 ASSERT_EQ(p2.x, 1u);
1305 ASSERT_EQ(p2.y, 2u);
1306 ASSERT_EQ(p2.z, 3u);
1307 }
1308 }

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

## ◆ TEST() [122/465]

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

Definition at line 1310 of file geometry_unittests.cc.

1310 {
1311 // LHS
1312 {
1313 Vector3 p1(1, 2, 3);
1314 Vector3 p2 = p1 + 2.0f;
1315 ASSERT_EQ(p2.x, 3);
1316 ASSERT_EQ(p2.y, 4);
1317 ASSERT_EQ(p2.z, 5);
1318 }
1319
1320 {
1321 Vector3 p1(1, 2, 3);
1322 Vector3 p2 = p1 - 2.0f;
1323 ASSERT_EQ(p2.x, -1);
1324 ASSERT_EQ(p2.y, 0);
1325 ASSERT_EQ(p2.z, 1);
1326 }
1327
1328 {
1329 Vector3 p1(1, 2, 3);
1330 Vector3 p2 = p1 * 2.0f;
1331 ASSERT_EQ(p2.x, 2);
1332 ASSERT_EQ(p2.y, 4);
1333 ASSERT_EQ(p2.z, 6);
1334 }
1335
1336 {
1337 Vector3 p1(2, 6, 12);
1338 Vector3 p2 = p1 / 2.0f;
1339 ASSERT_EQ(p2.x, 1);
1340 ASSERT_EQ(p2.y, 3);
1341 ASSERT_EQ(p2.z, 6);
1342 }
1343
1344 // RHS
1345 {
1346 Vector3 p1(1, 2, 3);
1347 Vector3 p2 = 2.0f + p1;
1348 ASSERT_EQ(p2.x, 3);
1349 ASSERT_EQ(p2.y, 4);
1350 ASSERT_EQ(p2.z, 5);
1351 }
1352
1353 {
1354 Vector3 p1(1, 2, 3);
1355 Vector3 p2 = 2.0f - p1;
1356 ASSERT_EQ(p2.x, 1);
1357 ASSERT_EQ(p2.y, 0);
1358 ASSERT_EQ(p2.z, -1);
1359 }
1360
1361 {
1362 Vector3 p1(1, 2, 3);
1363 Vector3 p2 = 2.0f * p1;
1364 ASSERT_EQ(p2.x, 2);
1365 ASSERT_EQ(p2.y, 4);
1366 ASSERT_EQ(p2.z, 6);
1367 }
1368
1369 {
1370 Vector3 p1(2, 6, 12);
1371 Vector3 p2 = 12.0f / p1;
1372 ASSERT_EQ(p2.x, 6);
1373 ASSERT_EQ(p2.y, 2);
1374 ASSERT_EQ(p2.z, 1);
1375 }
1376 }

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

## ◆ TEST() [123/465]

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

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

Definition at line 1226 of file geometry_unittests.cc.

1226 {
1227 {
1228 Vector3 p(1, 2, 4);
1229 p += Vector3(1, 2, 4);
1230 ASSERT_EQ(p.x, 2u);
1231 ASSERT_EQ(p.y, 4u);
1232 ASSERT_EQ(p.z, 8u);
1233 }
1234
1235 {
1236 Vector3 p(3, 6, 8);
1237 p -= Vector3(1, 2, 3);
1238 ASSERT_EQ(p.x, 2u);
1239 ASSERT_EQ(p.y, 4u);
1240 ASSERT_EQ(p.z, 5u);
1241 }
1242
1243 {
1244 Vector3 p(1, 2, 3);
1245 p *= Vector3(2, 3, 4);
1246 ASSERT_EQ(p.x, 2u);
1247 ASSERT_EQ(p.y, 6u);
1248 ASSERT_EQ(p.z, 12u);
1249 }
1250
1251 {
1252 Vector3 p(1, 2, 3);
1253 p *= 2;
1254 ASSERT_EQ(p.x, 2u);
1255 ASSERT_EQ(p.y, 4u);
1256 ASSERT_EQ(p.z, 6u);
1257 }
1258
1259 {
1260 Vector3 p(2, 6, 12);
1261 p /= Vector3(2, 3, 4);
1262 ASSERT_EQ(p.x, 1u);
1263 ASSERT_EQ(p.y, 2u);
1264 ASSERT_EQ(p.z, 3u);
1265 }
1266
1267 {
1268 Vector3 p(2, 6, 12);
1269 p /= 2;
1270 ASSERT_EQ(p.x, 1u);
1271 ASSERT_EQ(p.y, 3u);
1272 ASSERT_EQ(p.z, 6u);
1273 }
1274 }

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

## ◆ TEST() [125/465]

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

Definition at line 1483 of file geometry_unittests.cc.

1483 {
1484 {
1485 ColorMatrix color_matrix = {
1486 1, 1, 1, 1, 1, //
1487 1, 1, 1, 1, 1, //
1488 1, 1, 1, 1, 1, //
1489 1, 1, 1, 1, 1, //
1490 };
1491 auto result = Color::White().ApplyColorMatrix(color_matrix);
1492 auto expected = Color(1, 1, 1, 1);
1493 ASSERT_COLOR_NEAR(result, expected);
1494 }
1495
1496 {
1497 ColorMatrix color_matrix = {
1498 0.1, 0, 0, 0, 0.01, //
1499 0, 0.2, 0, 0, 0.02, //
1500 0, 0, 0.3, 0, 0.03, //
1501 0, 0, 0, 0.4, 0.04, //
1502 };
1503 auto result = Color::White().ApplyColorMatrix(color_matrix);
1504 auto expected = Color(0.11, 0.22, 0.33, 0.44);
1505 ASSERT_COLOR_NEAR(result, expected);
1506 }
1507 }

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

## ◆ TEST() [126/465]

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

Definition at line 1692 of file geometry_unittests.cc.

1692 {
1693 Color dst = ColorBlendTestData::kDestinationColor;
1694 for (size_t source_i = 0;
1695 source_i < sizeof(ColorBlendTestData::kSourceColors) / sizeof(Color);
1696 source_i++) {
1697 Color src = ColorBlendTestData::kSourceColors[source_i];
1698
1699 Color expected;
1700 IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_RESULT_CHECK)
1701 }
1702 }

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

## ◆ TEST() [127/465]

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

Definition at line 1443 of file geometry_unittests.cc.

1443 {
1444 {
1445 Color result = Color(0.5, 0.5, 0.5, 0.5).Clamp01();
1446 Color expected = Color(0.5, 0.5, 0.5, 0.5);
1447 ASSERT_COLOR_NEAR(result, expected);
1448 }
1449
1450 {
1451 Color result = Color(-1, -1, -1, -1).Clamp01();
1452 Color expected = Color(0, 0, 0, 0);
1453 ASSERT_COLOR_NEAR(result, expected);
1454 }
1455
1456 {
1457 Color result = Color(2, 2, 2, 2).Clamp01();
1458 Color expected = Color(1, 1, 1, 1);
1459 ASSERT_COLOR_NEAR(result, expected);
1460 }
1461 }

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

## ◆ TEST() [128/465]

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

Definition at line 1421 of file geometry_unittests.cc.

1421 {
1422 {
1423 Color a(0.0, 0.0, 0.0, 0.0);
1424 Color b(1.0, 1.0, 1.0, 1.0);
1425
1426 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.5, 0.5, 0.5, 0.5));
1427 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1428 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1429 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.2, 0.2, 0.2, 0.2));
1430 }
1431
1432 {
1433 Color a(0.2, 0.4, 1.0, 0.5);
1434 Color b(0.4, 1.0, 0.2, 0.3);
1435
1436 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.3, 0.7, 0.6, 0.4));
1437 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1438 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1439 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.24, 0.52, 0.84, 0.46));
1440 }
1441 }

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

## ◆ TEST() [129/465]

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

Definition at line 1509 of file geometry_unittests.cc.

1509 {
1510 {
1511 auto result = Color::White().LinearToSRGB();
1512 auto expected = Color(1, 1, 1, 1);
1513 ASSERT_COLOR_NEAR(result, expected);
1514 }
1515
1516 {
1517 auto result = Color::BlackTransparent().LinearToSRGB();
1518 auto expected = Color(0, 0, 0, 0);
1519 ASSERT_COLOR_NEAR(result, expected);
1520 }
1521
1522 {
1523 auto result = Color(0.2, 0.4, 0.6, 0.8).LinearToSRGB();
1524 auto expected = Color(0.484529, 0.665185, 0.797738, 0.8);
1525 ASSERT_COLOR_NEAR(result, expected);
1526 }
1527 }

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

## ◆ TEST() [130/465]

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

Definition at line 1463 of file geometry_unittests.cc.

1463 {
1464 {
1465 Color a = Color::MakeRGBA8(0, 0, 0, 0);
1466 Color b = Color::BlackTransparent();
1467 ASSERT_COLOR_NEAR(a, b);
1468 }
1469
1470 {
1471 Color a = Color::MakeRGBA8(255, 255, 255, 255);
1472 Color b = Color::White();
1473 ASSERT_COLOR_NEAR(a, b);
1474 }
1475
1476 {
1477 Color a = Color::MakeRGBA8(63, 127, 191, 127);
1478 Color b(0.247059, 0.498039, 0.74902, 0.498039);
1479 ASSERT_COLOR_NEAR(a, b);
1480 }
1481 }

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

## ◆ TEST() [131/465]

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

Definition at line 1378 of file geometry_unittests.cc.

1378 {
1379 {
1380 Color a(1.0, 0.5, 0.2, 0.5);
1381 Color premultiplied = a.Premultiply();
1382 Color expected = Color(0.5, 0.25, 0.1, 0.5);
1383 ASSERT_COLOR_NEAR(premultiplied, expected);
1384 }
1385
1386 {
1387 Color a(0.5, 0.25, 0.1, 0.5);
1388 Color unpremultiplied = a.Unpremultiply();
1389 Color expected = Color(1.0, 0.5, 0.2, 0.5);
1390 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1391 }
1392
1393 {
1394 Color a(0.5, 0.25, 0.1, 0.0);
1395 Color unpremultiplied = a.Unpremultiply();
1396 Color expected = Color(0.0, 0.0, 0.0, 0.0);
1397 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1398 }
1399 }

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

## ◆ TEST() [132/465]

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

Definition at line 1801 of file geometry_unittests.cc.

1801 {
1802 {
1803 std::stringstream stream;
1804 Color m;
1805 stream << m;
1806 ASSERT_EQ(stream.str(), "(0, 0, 0, 0)");
1807 }
1808
1809 {
1810 std::stringstream stream;
1811 Color m(1, 2, 3, 4);
1812 stream << m;
1813 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1814 }
1815 }

## ◆ TEST() [133/465]

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

Definition at line 1401 of file geometry_unittests.cc.

1401 {
1402 {
1403 Color a(1.0, 0.5, 0.2, 0.5);
1404 std::array<uint8_t, 4> expected = {255, 128, 51, 128};
1405 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1406 }
1407
1408 {
1409 Color a(0.0, 0.0, 0.0, 0.0);
1410 std::array<uint8_t, 4> expected = {0, 0, 0, 0};
1411 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1412 }
1413
1414 {
1415 Color a(1.0, 1.0, 1.0, 1.0);
1416 std::array<uint8_t, 4> expected = {255, 255, 255, 255};
1417 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1418 }
1419 }

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

## ◆ TEST() [134/465]

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

Definition at line 1529 of file geometry_unittests.cc.

1529 {
1530 {
1531 auto result = Color::White().SRGBToLinear();
1532 auto expected = Color(1, 1, 1, 1);
1533 ASSERT_COLOR_NEAR(result, expected);
1534 }
1535
1536 {
1537 auto result = Color::BlackTransparent().SRGBToLinear();
1538 auto expected = Color(0, 0, 0, 0);
1539 ASSERT_COLOR_NEAR(result, expected);
1540 }
1541
1542 {
1543 auto result = Color(0.2, 0.4, 0.6, 0.8).SRGBToLinear();
1544 auto expected = Color(0.0331048, 0.132868, 0.318547, 0.8);
1545 ASSERT_COLOR_NEAR(result, expected);
1546 }
1547 }

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

## ◆ TEST() [135/465]

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() [136/465]

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

Definition at line 1823 of file geometry_unittests.cc.

1823 {
1824 {
1825 // Simple 2 color gradient produces color buffer containing exactly those
1826 // values.
1827 std::vector<Color> colors = {Color::Red(), Color::Blue()};
1828 std::vector<Scalar> stops = {0.0, 1.0};
1829
1830 auto gradient = CreateGradientBuffer(colors, stops);
1831
1832 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1833 ASSERT_EQ(gradient.texture_size, 2u);
1834 }
1835
1836 {
1837 // Gradient with duplicate stops does not create an empty texture.
1838 std::vector<Color> colors = {Color::Red(), Color::Yellow(), Color::Black(),
1839 Color::Blue()};
1840 std::vector<Scalar> stops = {0.0, 0.25, 0.25, 1.0};
1841
1842 auto gradient = CreateGradientBuffer(colors, stops);
1843 ASSERT_EQ(gradient.texture_size, 5u);
1844 }
1845
1846 {
1847 // Simple N color gradient produces color buffer containing exactly those
1848 // values.
1849 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green(),
1850 Color::White()};
1851 std::vector<Scalar> stops = {0.0, 0.33, 0.66, 1.0};
1852
1853 auto gradient = CreateGradientBuffer(colors, stops);
1854
1855 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1856 ASSERT_EQ(gradient.texture_size, 4u);
1857 }
1858
1859 {
1860 // Gradient with color stops will lerp and scale buffer.
1861 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green()};
1862 std::vector<Scalar> stops = {0.0, 0.25, 1.0};
1863
1864 auto gradient = CreateGradientBuffer(colors, stops);
1865
1866 std::vector<Color> lerped_colors = {
1867 Color::Red(),
1868 Color::Blue(),
1869 Color::Lerp(Color::Blue(), Color::Green(), 0.3333),
1870 Color::Lerp(Color::Blue(), Color::Green(), 0.6666),
1871 Color::Green(),
1872 };
1873 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, lerped_colors);
1874 ASSERT_EQ(gradient.texture_size, 5u);
1875 }
1876
1877 {
1878 // Gradient size is capped at 1024.
1879 std::vector<Color> colors = {};
1880 std::vector<Scalar> stops = {};
1881 for (auto i = 0u; i < 1025; i++) {
1882 colors.push_back(Color::Blue());
1883 stops.push_back(i / 1025.0);
1884 }
1885
1886 auto gradient = CreateGradientBuffer(colors, stops);
1887
1888 ASSERT_EQ(gradient.texture_size, 1024u);
1889 ASSERT_EQ(gradient.color_bytes.size(), 1024u * 4);
1890 }
1891 }

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

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

Definition at line 1893 of file geometry_unittests.cc.

1893 {
1894 #if defined(FML_OS_MACOSX) || defined(FML_OS_IOS) || \
1895 defined(FML_OS_IOS_SIMULATOR)
1896 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
1897 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
1898 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
1899 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
1900
1901 // 65504 is the largest possible half.
1902 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
1903 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
1904
1905 // Colors
1906 ASSERT_EQ(HalfVector4(Color::Red()),
1907 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
1908 ASSERT_EQ(HalfVector4(Color::Green()),
1909 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
1910 ASSERT_EQ(HalfVector4(Color::Blue()),
1911 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
1912 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
1913 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
1914
1915 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
1916 HalfVector3(4.0f16, 6.0f16, -1.0f16));
1917 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
1918
1919 ASSERT_EQ(Half(0.5f), Half(0.5f16));
1920 ASSERT_EQ(Half(0.5), Half(0.5f16));
1921 ASSERT_EQ(Half(5), Half(5.0f16));
1922 #else
1923 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
1924 "only used on Apple platforms.";
1925 #endif // FML_OS_MACOSX || FML_OS_IOS || FML_OS_IOS_SIMULATOR
1926 }

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

## ◆ TEST() [138/465]

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

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

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() [141/465]

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() [142/465]

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() [143/465]

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(), impeller::Matrix::MakeScale(), and x.

## ◆ TEST() [144/465]

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() [145/465]

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() [146/465]

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() [147/465]

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() [148/465]

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() [149/465]

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() [150/465]

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

Definition at line 1726 of file geometry_unittests.cc.

1726 {
1727 {
1728 std::stringstream stream;
1729 Matrix m;
1730 stream << m;
1731 ASSERT_EQ(stream.str(), R"((
1732 1.000000, 0.000000, 0.000000, 0.000000,
1733 0.000000, 1.000000, 0.000000, 0.000000,
1734 0.000000, 0.000000, 1.000000, 0.000000,
1735 0.000000, 0.000000, 0.000000, 1.000000,
1736 ))");
1737 }
1738
1739 {
1740 std::stringstream stream;
1741 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
1742 stream << m;
1743
1744 ASSERT_EQ(stream.str(), R"((
1745 1.000000, 0.000000, 0.000000, 10.000000,
1746 0.000000, 1.000000, 0.000000, 20.000000,
1747 0.000000, 0.000000, 1.000000, 30.000000,
1748 0.000000, 0.000000, 0.000000, 1.000000,
1749 ))");
1750 }
1751 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [151/465]

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() [152/465]

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() [153/465]

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() [154/465]

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() [155/465]

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() [156/465]

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

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

Definition at line 1113 of file geometry_unittests.cc.

1113 {
1114 Point p(1.5, 2.3);
1115 Point result = p.Ceil();
1116 Point expected(2, 3);
1117 ASSERT_POINT_NEAR(result, expected);
1118 }

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

## ◆ TEST() [158/465]

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() [159/465]

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() [160/465]

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

Definition at line 1092 of file geometry_unittests.cc.

1092 {
1093 Point p(1.5, 2.3);
1094 Point result = p.Floor();
1095 Point expected(1, 2);
1096 ASSERT_POINT_NEAR(result, expected);
1097 }

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

## ◆ TEST() [161/465]

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() [162/465]

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

Definition at line 1155 of file geometry_unittests.cc.

1155 {
1156 Point p(1, 2);
1157 Point result = p.Lerp({5, 10}, 0.75);
1158 Point expected(4, 8);
1159 ASSERT_POINT_NEAR(result, expected);
1160 }

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

## ◆ TEST() [163/465]

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

Definition at line 1071 of file geometry_unittests.cc.

1071 {
1072 Point p(1, 2);
1073 Point result = p.Max({0, 10});
1074 Point expected(1, 10);
1075 ASSERT_POINT_NEAR(result, expected);
1076 }

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

## ◆ TEST() [164/465]

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

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

Definition at line 1753 of file geometry_unittests.cc.

1753 {
1754 {
1755 std::stringstream stream;
1756 Point m;
1757 stream << m;
1758 ASSERT_EQ(stream.str(), "(0, 0)");
1759 }
1760
1761 {
1762 std::stringstream stream;
1763 Point m(13, 37);
1764 stream << m;
1765 ASSERT_EQ(stream.str(), "(13, 37)");
1766 }
1767 }

## ◆ TEST() [166/465]

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

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() [168/465]

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

Definition at line 1134 of file geometry_unittests.cc.

1134 {
1135 Point p(1.5, 2.3);
1136 Point result = p.Round();
1137 Point expected(2, 2);
1138 ASSERT_POINT_NEAR(result, expected);
1139 }

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

## ◆ TEST() [169/465]

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

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() [171/465]

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() [172/465]

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() [173/465]

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

Definition at line 1210 of file geometry_unittests.cc.

1210 {
1211 {
1212 SeparatedVector2 v(Vector2(10, 0));
1213 Radians actual = v.AngleTo(SeparatedVector2(Vector2(5, 0)));
1214 Radians expected = Radians{0};
1215 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1216 }
1217
1218 {
1219 SeparatedVector2 v(Vector2(10, 0));
1220 Radians actual = v.AngleTo(SeparatedVector2(Vector2(0, -5)));
1221 Radians expected = Radians{-kPi / 2};
1222 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1223 }
1224 }

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

## ◆ TEST() [174/465]

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

Definition at line 1187 of file geometry_unittests.cc.

1187 {
1188 // Parallel
1189 {
1190 SeparatedVector2 v(Vector2(10, 0));
1191 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(5, 0)));
1192 ASSERT_NEAR(actual, 1, kEhCloseEnough);
1193 }
1194
1195 // Perpendicular
1196 {
1197 SeparatedVector2 v(Vector2(10, 0));
1198 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, 5)));
1199 ASSERT_NEAR(actual, 0, kEhCloseEnough);
1200 }
1201
1202 // Opposite parallel
1203 {
1204 SeparatedVector2 v(Vector2(0, 10));
1205 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, -5)));
1206 ASSERT_NEAR(actual, -1, kEhCloseEnough);
1207 }
1208 }

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

## ◆ TEST() [175/465]

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

Definition at line 1182 of file geometry_unittests.cc.

1182 {
1183 SeparatedVector2 v(Vector2(10, 0));
1184 ASSERT_POINT_NEAR(v.GetVector(), Vector2(10, 0));
1185 }

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

## ◆ TEST() [176/465]

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

Definition at line 1176 of file geometry_unittests.cc.

1176 {
1177 SeparatedVector2 v(Vector2(10, 0));
1178 ASSERT_POINT_NEAR(v.direction, Vector2(1, 0));
1179 ASSERT_NEAR(v.magnitude, 10, kEhCloseEnough);
1180 }

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

## ◆ TEST() [177/465]

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() [178/465]

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() [179/465]

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() [180/465]

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() [181/465]

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() [182/465]

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

Definition at line 1817 of file geometry_unittests.cc.

1817 {
1818 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
1819 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
1820 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
1821 }

References impeller::Color::ToIColor().

## ◆ TEST() [183/465]

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

Definition at line 1120 of file geometry_unittests.cc.

1120 {
1121 Vector3 p(1.5, 2.3, 3.9);
1122 Vector3 result = p.Ceil();
1123 Vector3 expected(2, 3, 4);
1124 ASSERT_VECTOR3_NEAR(result, expected);
1125 }

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

## ◆ TEST() [184/465]

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

Definition at line 1099 of file geometry_unittests.cc.

1099 {
1100 Vector3 p(1.5, 2.3, 3.9);
1101 Vector3 result = p.Floor();
1102 Vector3 expected(1, 2, 3);
1103 ASSERT_VECTOR3_NEAR(result, expected);
1104 }

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

## ◆ TEST() [185/465]

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

Definition at line 1162 of file geometry_unittests.cc.

1162 {
1163 Vector3 p(1, 2, 3);
1164 Vector3 result = p.Lerp({5, 10, 15}, 0.75);
1165 Vector3 expected(4, 8, 12);
1166 ASSERT_VECTOR3_NEAR(result, expected);
1167 }

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

## ◆ TEST() [186/465]

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

Definition at line 1078 of file geometry_unittests.cc.

1078 {
1079 Vector3 p(1, 2, 3);
1080 Vector3 result = p.Max({0, 10, 2});
1081 Vector3 expected(1, 10, 3);
1082 ASSERT_VECTOR3_NEAR(result, expected);
1083 }

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

## ◆ TEST() [187/465]

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

Definition at line 1057 of file geometry_unittests.cc.

1057 {
1058 Vector3 p(1, 2, 3);
1059 Vector3 result = p.Min({0, 10, 2});
1060 Vector3 expected(0, 2, 2);
1061 ASSERT_VECTOR3_NEAR(result, expected);
1062 }

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

## ◆ TEST() [188/465]

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

Definition at line 1769 of file geometry_unittests.cc.

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

## ◆ TEST() [189/465]

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

Definition at line 1141 of file geometry_unittests.cc.

1141 {
1142 Vector3 p(1.5, 2.3, 3.9);
1143 Vector3 result = p.Round();
1144 Vector3 expected(2, 2, 4);
1145 ASSERT_VECTOR3_NEAR(result, expected);
1146 }

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

## ◆ TEST() [190/465]

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

Definition at line 1127 of file geometry_unittests.cc.

1127 {
1128 Vector4 p(1.5, 2.3, 3.9, 4.0);
1129 Vector4 result = p.Ceil();
1130 Vector4 expected(2, 3, 4, 4);
1131 ASSERT_VECTOR4_NEAR(result, expected);
1132 }

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

## ◆ TEST() [191/465]

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

Definition at line 1106 of file geometry_unittests.cc.

1106 {
1107 Vector4 p(1.5, 2.3, 3.9, 4.0);
1108 Vector4 result = p.Floor();
1109 Vector4 expected(1, 2, 3, 4);
1110 ASSERT_VECTOR4_NEAR(result, expected);
1111 }

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

## ◆ TEST() [192/465]

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

Definition at line 1011 of file geometry_unittests.cc.

1011 {
1012 {
1013 Vector4 v;
1014 ASSERT_TRUE(v.IsFinite());
1015 v.x = std::numeric_limits<Scalar>::infinity();
1016 ASSERT_FALSE(v.IsFinite());
1017 v.x = -std::numeric_limits<Scalar>::infinity();
1018 ASSERT_FALSE(v.IsFinite());
1019 v.x = -std::numeric_limits<Scalar>::quiet_NaN();
1020 ASSERT_FALSE(v.IsFinite());
1021 }
1022
1023 {
1024 Vector4 v;
1025 ASSERT_TRUE(v.IsFinite());
1026 v.y = std::numeric_limits<Scalar>::infinity();
1027 ASSERT_FALSE(v.IsFinite());
1028 v.y = -std::numeric_limits<Scalar>::infinity();
1029 ASSERT_FALSE(v.IsFinite());
1030 v.y = -std::numeric_limits<Scalar>::quiet_NaN();
1031 ASSERT_FALSE(v.IsFinite());
1032 }
1033
1034 {
1035 Vector4 v;
1036 ASSERT_TRUE(v.IsFinite());
1037 v.z = std::numeric_limits<Scalar>::infinity();
1038 ASSERT_FALSE(v.IsFinite());
1039 v.z = -std::numeric_limits<Scalar>::infinity();
1040 ASSERT_FALSE(v.IsFinite());
1041 v.z = -std::numeric_limits<Scalar>::quiet_NaN();
1042 ASSERT_FALSE(v.IsFinite());
1043 }
1044
1045 {
1046 Vector4 v;
1047 ASSERT_TRUE(v.IsFinite());
1048 v.w = std::numeric_limits<Scalar>::infinity();
1049 ASSERT_FALSE(v.IsFinite());
1050 v.w = -std::numeric_limits<Scalar>::infinity();
1051 ASSERT_FALSE(v.IsFinite());
1052 v.w = -std::numeric_limits<Scalar>::quiet_NaN();
1053 ASSERT_FALSE(v.IsFinite());
1054 }
1055 }

References impeller::Vector4::IsFinite(), impeller::Vector4::w, impeller::Vector4::x, impeller::Vector4::y, and impeller::Vector4::z.

## ◆ TEST() [193/465]

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

Definition at line 1169 of file geometry_unittests.cc.

1169 {
1170 Vector4 p(1, 2, 3, 4);
1171 Vector4 result = p.Lerp({5, 10, 15, 20}, 0.75);
1172 Vector4 expected(4, 8, 12, 16);
1173 ASSERT_VECTOR4_NEAR(result, expected);
1174 }

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

## ◆ TEST() [194/465]

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

Definition at line 1085 of file geometry_unittests.cc.

1085 {
1086 Vector4 p(1, 2, 3, 4);
1087 Vector4 result = p.Max({0, 10, 2, 1});
1088 Vector4 expected(1, 10, 3, 4);
1089 ASSERT_VECTOR4_NEAR(result, expected);
1090 }

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

## ◆ TEST() [195/465]

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

Definition at line 1064 of file geometry_unittests.cc.

1064 {
1065 Vector4 p(1, 2, 3, 4);
1066 Vector4 result = p.Min({0, 10, 2, 1});
1067 Vector4 expected(0, 2, 2, 1);
1068 ASSERT_VECTOR4_NEAR(result, expected);
1069 }

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

## ◆ TEST() [196/465]

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

Definition at line 1785 of file geometry_unittests.cc.

1785 {
1786 {
1787 std::stringstream stream;
1788 Vector4 m;
1789 stream << m;
1790 ASSERT_EQ(stream.str(), "(0, 0, 0, 1)");
1791 }
1792
1793 {
1794 std::stringstream stream;
1795 Vector4 m(1, 2, 3, 4);
1796 stream << m;
1797 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1798 }
1799 }

## ◆ TEST() [197/465]

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

Definition at line 1148 of file geometry_unittests.cc.

1148 {
1149 Vector4 p(1.5, 2.3, 3.9, 4.0);
1150 Vector4 result = p.Round();
1151 Vector4 expected(2, 2, 4, 4);
1152 ASSERT_VECTOR4_NEAR(result, expected);
1153 }

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

## ◆ TEST() [198/465]

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

Definition at line 65 of file matrix_filter_contents_unittests.cc.

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

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

## ◆ TEST() [199/465]

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

Definition at line 77 of file matrix_filter_contents_unittests.cc.

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

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

## ◆ TEST() [200/465]

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

Definition at line 45 of file matrix_filter_contents_unittests.cc.

45 {
46 MatrixFilterContents contents;
47 FilterInput::Vector inputs = {};
48 Entity entity;
49 std::optional<Rect> coverage =
50 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
51 ASSERT_FALSE(coverage.has_value());
52 }

References impeller::MatrixFilterContents::GetFilterCoverage().

## ◆ TEST() [201/465]

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

Definition at line 54 of file matrix_filter_contents_unittests.cc.

54 {
55 MatrixFilterContents contents;
56 FilterInput::Vector inputs = {
57 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
58 Entity entity;
59 std::optional<Rect> coverage =
60 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
61
62 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
63 }

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

## ◆ TEST() [202/465]

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 x.

## ◆ TEST() [203/465]

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

Definition at line 263 of file matrix_unittests.cc.

263 {
264 Matrix m = Matrix::MakeScale({-2, 1, 1});
265
266 EXPECT_EQ(m.GetMaxBasisLengthXY(), 2);
267
268 m = Matrix::MakeScale({1, -3, 1});
269
270 EXPECT_EQ(m.GetMaxBasisLengthXY(), 3);
271 }

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

## ◆ TEST() [204/465]

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

Definition at line 274 of file matrix_unittests.cc.

274 {
275 Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
276 EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e+20, 1e+20);
277
278 m = Matrix::MakeScale({2.625e-20, 2.625e-20, 1});
279 EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e-20, 1e-20);
280 }

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

## ◆ TEST() [205/465]

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

Definition at line 282 of file matrix_unittests.cc.

282 {
283 Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
284 m.e[0][1] = 2;
285
286 EXPECT_TRUE(std::isinf(m.GetMaxBasisLengthXY()));
287 }

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

## ◆ TEST() [206/465]

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() [207/465]

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() [208/465]

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() [209/465]

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

Definition at line 203 of file matrix_unittests.cc.

203 {
204 EXPECT_TRUE(Matrix().IsAligned());
205 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned());
206
207 // Begin Legacy tests transferred over from geometry_unittests.cc
208 {
209 auto m = Matrix::MakeTranslation({1, 2, 3});
210 bool result = m.IsAligned();
211 ASSERT_TRUE(result);
212 }
213
214 {
215 auto m = Matrix::MakeRotationZ(Degrees{123});
216 bool result = m.IsAligned();
217 ASSERT_FALSE(result);
218 }
219 // End Legacy tests transferred over from geometry_unittests.cc
220
221 auto test = [](int index, bool expect) {
222 Matrix matrix;
223 EXPECT_TRUE(matrix.IsAligned());
224 matrix.m[index] = 0.5f;
225 EXPECT_EQ(matrix.IsAligned(), expect) << "index: " << index;
226 };
227
228 // clang-format off
229 test( 0, true); test( 1, false); test( 2, false); test( 3, false);
230 test( 4, false); test( 5, true); test( 6, false); test( 7, false);
231 test( 8, false); test( 9, false); test(10, true); test(11, false);
232 test(12, true); test(13, true); test(14, true); test(15, false);
233 // clang-format on
234
235 // True for quadrant rotations from -250 to +250 full circles
236 for (int i = -1000; i < 1000; i++) {
237 Degrees d = Degrees(i * 90);
238 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
239 EXPECT_TRUE(matrix.IsAligned()) << "degrees: " << d.degrees;
240 }
241
242 // False for half degree rotations from -999.5 to +1000.5 degrees
243 for (int i = -1000; i < 1000; i++) {
244 Degrees d = Degrees(i + 0.5f);
245 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
246 EXPECT_FALSE(matrix.IsAligned()) << "degrees: " << d.degrees;
247 }
248 }

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

## ◆ TEST() [210/465]

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

Definition at line 170 of file matrix_unittests.cc.

170 {
171 EXPECT_TRUE(Matrix().IsAligned2D());
172 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
173
174 auto test = [](int index, bool expect) {
175 Matrix matrix;
176 EXPECT_TRUE(matrix.IsAligned2D());
177 matrix.m[index] = 0.5f;
178 EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
179 };
180
181 // clang-format off
182 test( 0, true); test( 1, false); test( 2, true); test( 3, false);
183 test( 4, false); test( 5, true); test( 6, true); test( 7, false);
184 test( 8, true); test( 9, true); test(10, true); test(11, true);
185 test(12, true); test(13, true); test(14, true); test(15, false);
186 // clang-format on
187
188 // True for quadrant rotations from -250 to +250 full circles
189 for (int i = -1000; i < 1000; i++) {
190 Degrees d = Degrees(i * 90);
191 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
192 EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
193 }
194
195 // False for half degree rotations from -999.5 to +1000.5 degrees
196 for (int i = -1000; i < 1000; i++) {
197 Degrees d = Degrees(i + 0.5f);
198 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
199 EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
200 }
201 }

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

## ◆ TEST() [211/465]

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

Definition at line 132 of file matrix_unittests.cc.

132 {
133 EXPECT_TRUE(Matrix().IsFinite());
134
135 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsFinite());
136 EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsFinite());
137
138 EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsFinite());
139 EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsFinite());
140 EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsFinite());
141
142 EXPECT_TRUE(Matrix::MakeScale({0, 1, 1}).IsFinite());
143 EXPECT_TRUE(Matrix::MakeScale({1, 0, 1}).IsFinite());
144 EXPECT_TRUE(Matrix::MakeScale({1, 1, 0}).IsFinite());
145
146 for (int i = 0; i < 16; i++) {
147 {
148 Matrix matrix;
149 ASSERT_TRUE(matrix.IsFinite());
150 matrix.m[i] = std::numeric_limits<Scalar>::infinity();
151 ASSERT_FALSE(matrix.IsFinite());
152 }
153
154 {
155 Matrix matrix;
156 ASSERT_TRUE(matrix.IsFinite());
157 matrix.m[i] = -std::numeric_limits<Scalar>::infinity();
158 ASSERT_FALSE(matrix.IsFinite());
159 }
160
161 {
162 Matrix matrix;
163 ASSERT_TRUE(matrix.IsFinite());
164 matrix.m[i] = -std::numeric_limits<Scalar>::quiet_NaN();
165 ASSERT_FALSE(matrix.IsFinite());
166 }
167 }
168 }

References impeller::Matrix::IsFinite(), impeller::Matrix::m, impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [212/465]

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

Definition at line 105 of file matrix_unittests.cc.

105 {
106 EXPECT_TRUE(Matrix().IsInvertible());
107 EXPECT_NE(Matrix().GetDeterminant(), 0.0f);
108
109 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsInvertible());
110 EXPECT_NE(Matrix::MakeTranslation({100, 100, 0}).GetDeterminant(), 0.0f);
111
112 EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsInvertible());
113 EXPECT_NE(Matrix::MakeScale({100, 100, 1}).GetDeterminant(), 0.0f);
114
115 EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsInvertible());
116 EXPECT_NE(Matrix::MakeRotationX(Degrees(30)).GetDeterminant(), 0.0f);
117
118 EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsInvertible());
119 EXPECT_NE(Matrix::MakeRotationY(Degrees(30)).GetDeterminant(), 0.0f);
120
121 EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsInvertible());
122 EXPECT_NE(Matrix::MakeRotationZ(Degrees(30)).GetDeterminant(), 0.0f);
123
124 EXPECT_FALSE(Matrix::MakeScale({0, 1, 1}).IsInvertible());
125 EXPECT_EQ(Matrix::MakeScale({0, 1, 1}).GetDeterminant(), 0.0f);
126 EXPECT_FALSE(Matrix::MakeScale({1, 0, 1}).IsInvertible());
127 EXPECT_EQ(Matrix::MakeScale({1, 0, 1}).GetDeterminant(), 0.0f);
128 EXPECT_FALSE(Matrix::MakeScale({1, 1, 0}).IsInvertible());
129 EXPECT_EQ(Matrix::MakeScale({1, 1, 0}).GetDeterminant(), 0.0f);
130 }

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

## ◆ TEST() [213/465]

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

Definition at line 83 of file matrix_unittests.cc.

83 {
84 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationOnly());
85 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationScaleOnly());
86 EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationOnly());
87 EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationScaleOnly());
88 EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationOnly());
89 EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationScaleOnly());
90 EXPECT_TRUE(Matrix().IsTranslationOnly());
91 EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
92 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [214/465]

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

Definition at line 94 of file matrix_unittests.cc.

94 {
95 EXPECT_FALSE(Matrix::MakeScale({100, 100, 1}).IsTranslationOnly());
96 EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsTranslationScaleOnly());
97 EXPECT_FALSE(Matrix::MakeScale({1, 100, 1}).IsTranslationOnly());
98 EXPECT_TRUE(Matrix::MakeScale({1, 100, 1}).IsTranslationScaleOnly());
99 EXPECT_FALSE(Matrix::MakeScale({100, 1, 1}).IsTranslationOnly());
100 EXPECT_TRUE(Matrix::MakeScale({100, 1, 1}).IsTranslationScaleOnly());
101 EXPECT_TRUE(Matrix().IsTranslationOnly());
102 EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
103 }

References impeller::Matrix::MakeScale().

## ◆ TEST() [215/465]

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

Definition at line 301 of file matrix_unittests.cc.

301 {
302 EXPECT_TRUE(MatrixNear(
303 Matrix::MakeTranslateScale({1, 1, 1.0 / 1024}, {10, 10, 1.0 / 1024}),
304 Matrix::MakeTranslation({10, 10, 1.0 / 1024}) *
305 Matrix::MakeScale({1, 1, 1.0 / 1024})));
306
307 EXPECT_TRUE(MatrixNear(
308 Matrix::MakeTranslateScale({2, 2, 2}, {10, 10, 0}),
309 Matrix::MakeTranslation({10, 10, 0}) * Matrix::MakeScale({2, 2, 2})));
310
311 EXPECT_TRUE(MatrixNear(
312 Matrix::MakeTranslateScale({0, 0, 0}, {0, 0, 0}),
313 Matrix::MakeTranslation({0, 0, 0}) * Matrix::MakeScale({0, 0, 0})));
314 }

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

## ◆ TEST() [216/465]

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(), MatrixNear(), and x.

## ◆ TEST() [217/465]

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 x.

## ◆ TEST() [218/465]

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

Definition at line 250 of file matrix_unittests.cc.

250 {
251 Matrix matrix = Matrix::MakeColumn(
252 // clang-format off
253 2.0f, 3.0f, 5.0f, 7.0f,
254 11.0f, 13.0f, 17.0f, 19.0f,
255 23.0f, 29.0f, 31.0f, 37.0f,
256 41.0f, 43.0f, 47.0f, 53.0f
257 // clang-format on
258 );
259 EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
260 Vector3(32.0f, 33.0f, 41.0f));
261 }

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

## ◆ TEST() [219/465]

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

Definition at line 289 of file matrix_unittests.cc.

289 {
290 Matrix m = Matrix::MakeRow(1.0, 0.0, 0.0, 10.0, //
291 0.0, 1.0, 0.0, 20.0, //
292 0.0, 0.0, 1.0, 0.0, //
293 0.0, 2.0, 0.0, 30.0);
294 Matrix result = m.Translate({100, 200});
295 EXPECT_TRUE(MatrixNear(result, Matrix::MakeRow(1.0, 0.0, 0.0, 110.0, //
296 0.0, 1.0, 0.0, 220.0, //
297 0.0, 0.0, 1.0, 0.0, //
298 0.0, 2.0, 0.0, 430.0)));
299 }

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

## ◆ TEST() [220/465]

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

Definition at line 485 of file path_unittests.cc.

485 {
486 PathBuilder builder;
487 auto path =
488 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
489 .TakePath();
490 auto box = path.GetBoundingBox();
491 Rect expected = Rect::MakeXYWH(93.9101, 40, 126.09, 158.862);
492 ASSERT_TRUE(box.has_value());
493 ASSERT_RECT_NEAR(box.value_or(Rect::MakeMaximum()), expected);
494 }

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

## ◆ TEST() [221/465]

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

Definition at line 496 of file path_unittests.cc.

496 {
497 PathBuilder builder;
498 builder.AddRoundRect(
499 RoundRect::MakeRectRadius(Rect::MakeXYWH(10, 10, 300, 300), 50));
500 auto path = builder.TakePath();
501 auto actual = path.GetBoundingBox();
502 Rect expected = Rect::MakeXYWH(10, 10, 300, 300);
503
504 ASSERT_TRUE(actual.has_value());
505 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
506 }

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

## ◆ TEST() [222/465]

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

Definition at line 666 of file path_unittests.cc.

666 {
667 PathBuilder builder;
668 builder.MoveTo({10, 10});
669 builder.LineTo({20, 20});
670 builder.SetBounds(Rect::MakeLTRB(0, 0, 100, 100));
671 builder.SetConvexity(Convexity::kConvex);
672
673 auto path_a = builder.TakePath(FillType::kOdd);
674 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
675 auto path_b = path_a;
676
677 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
678 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
679 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
680
681 auto poly_a = path_a.CreatePolyline(1.0);
682 auto poly_b = path_b.CreatePolyline(1.0);
683
684 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
685 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
686
687 for (auto i = 0u; i < poly_a.points->size(); i++) {
688 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
689 }
690
691 for (auto i = 0u; i < poly_a.contours.size(); i++) {
692 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
693 EXPECT_EQ(poly_a.contours[i].start_direction,
694 poly_b.contours[i].start_direction);
695 }
696 }

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() [223/465]

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

Definition at line 636 of file path_unittests.cc.

636 {
637 PathBuilder builder;
638 auto path = builder.LineTo({0, 10})
639 .LineTo({10, 10})
640 .MoveTo({30, 30}) // Moves to (30, 30)
641 .Close() // No Op
642 .Close() // Still No op
643 .TakePath();
644
645 EXPECT_EQ(path.GetComponentCount(), 4u);
646 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 2u);
647 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
648 }

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

## ◆ TEST() [224/465]

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

Definition at line 650 of file path_unittests.cc.

650 {
651 PathBuilder builder;
652 // Create a path that has a current position at the origin when close is
653 // called. This should not insert a new line segment
654 auto path = builder.LineTo({10, 0})
655 .LineTo({10, 10})
656 .LineTo({0, 10})
657 .LineTo({0, 0})
658 .Close()
659 .TakePath();
660
661 EXPECT_EQ(path.GetComponentCount(), 6u);
662 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 4u);
663 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
664 }

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

## ◆ TEST() [225/465]

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

Definition at line 470 of file path_unittests.cc.

470 {
471 PathBuilder builder;
472 auto path =
473 builder.CubicCurveTo(Point(10, 10), Point(-10, -10), Point(20, 20))
474 .TakePath();
475
476 CubicPathComponent cubic;
477 path.GetCubicComponentAtIndex(1, cubic);
478
479 EXPECT_EQ(cubic.p1, Point(0, 0));
480 EXPECT_EQ(cubic.cp1, Point(10, 10));
481 EXPECT_EQ(cubic.cp2, Point(-10, -10));
482 EXPECT_EQ(cubic.p2, Point(20, 20));
483 }

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

## ◆ TEST() [226/465]

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

Definition at line 17 of file path_unittests.cc.

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

References polyline.

## ◆ TEST() [227/465]

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

Definition at line 531 of file path_unittests.cc.

531 {
532 auto path = PathBuilder{}.TakePath();
533 ASSERT_EQ(path.GetComponentCount(), 1u);
534
535 ContourComponent c;
536 path.GetContourComponentAtIndex(0, c);
537 ASSERT_POINT_NEAR(c.destination, Point());
538
539 Path::Polyline polyline = path.CreatePolyline(1.0f);
540 ASSERT_TRUE(polyline.points->empty());
541 ASSERT_TRUE(polyline.contours.empty());
542 }

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

## ◆ TEST() [228/465]

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

Definition at line 27 of file path_unittests.cc.

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

References impeller::PathBuilder::TakePath().

## ◆ TEST() [229/465]

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

Definition at line 508 of file path_unittests.cc.

508 {
509 CubicPathComponent cubic{{11.769268, 252.883148},
510 {-6.2857933, 204.356461},
511 {-4.53997231, 156.552902},
512 {17.0067291, 109.472488}};
513 auto points = cubic.Extrema();
514
515 ASSERT_EQ(points.size(), static_cast<size_t>(3));
516 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
517 }

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

## ◆ TEST() [230/465]

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

Definition at line 698 of file path_unittests.cc.

698 {
699 Path path = PathBuilder{}
700 .AddRoundRect(RoundRect::MakeRectRadius(
701 Rect::MakeLTRB(0, 0, 100, 100), 10))
702 .TakePath();
703 auto [points, contours] = path.CountStorage(1.0);
704
705 std::vector<Point> point_storage(points);
706 std::vector<uint16_t> index_storage(points + (contours - 1));
707
708 FanVertexWriter writer(point_storage.data(), index_storage.data());
709 path.WritePolyline(1.0, writer);
710
711 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
712 EXPECT_EQ(point_storage[0], Point(10, 0));
713 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::FanVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), impeller::PathBuilder::TakePath(), and impeller::Path::WritePolyline().

## ◆ TEST() [231/465]

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

Definition at line 765 of file path_unittests.cc.

765 {
766 PathBuilder builder{};
767 for (auto i = 0; i < 10; i++) {
768 builder.AddRoundRect(
769 RoundRect::MakeRectRadius(Rect::MakeLTRB(0 + i, 0 + i, 100, 100), 10));
770 }
771 auto path = builder.TakePath();
772 auto [points, contours] = path.CountStorage(1.0);
773
774 std::vector<Point> point_storage(points);
775 std::vector<uint16_t> index_storage(points + (contours - 1));
776
777 FanVertexWriter writer(point_storage.data(), index_storage.data());
778 path.WritePolyline(1.0, writer);
779
780 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
781 EXPECT_EQ(point_storage[0], Point(10, 0));
782 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::FanVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [232/465]

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

Definition at line 716 of file path_unittests.cc.

716 {
717 // Create a rectangle that lacks an explicit close.
718 Path path = PathBuilder{}
719 .LineTo({100, 0})
720 .LineTo({100, 100})
721 .LineTo({0, 100})
722 .TakePath();
723
724 std::vector<Point> expected = {{0, 0}, {100, 0}, {100, 100},
725 {0, 100}, {0, 0}, {0, 0}};
726 std::vector<uint16_t> expected_indices = {0, 1, 2, 3, 0xFFFF, 0};
727
728 auto [points, contours] = path.CountStorage(1.0);
729
730 std::vector<Point> point_storage(points);
731 std::vector<uint16_t> index_storage(points + (contours - 1));
732
733 FanVertexWriter writer(point_storage.data(), index_storage.data());
734 path.WritePolyline(1.0, writer);
735
736 EXPECT_LE(index_storage, expected_indices);
737 EXPECT_EQ(point_storage, expected);
738 }

References impeller::Path::CountStorage(), impeller::LineTo(), impeller::PathBuilder::LineTo(), and impeller::Path::WritePolyline().

## ◆ TEST() [233/465]

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

Definition at line 306 of file path_unittests.cc.

306 {
307 Path::Polyline polyline = PathBuilder{}
308 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
309 .TakePath()
310 .CreatePolyline(1.0f);
311 ASSERT_EQ(polyline.contours.size(), 1u);
312 ASSERT_TRUE(polyline.contours[0].is_closed);
313 ASSERT_EQ(polyline.contours[0].start_index, 0u);
314 ASSERT_EQ(polyline.points->size(), 5u);
315 ASSERT_EQ(polyline.GetPoint(0), Point(50, 60));
316 ASSERT_EQ(polyline.GetPoint(1), Point(70, 60));
317 ASSERT_EQ(polyline.GetPoint(2), Point(70, 80));
318 ASSERT_EQ(polyline.GetPoint(3), Point(50, 80));
319 ASSERT_EQ(polyline.GetPoint(4), Point(50, 60));
320 }

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

## ◆ TEST() [234/465]

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

Definition at line 820 of file path_unittests.cc.

820 {
821 auto test_isolation =
822 [](const std::function<void(PathBuilder & builder)>& mutator,
823 bool will_close, Point mutation_offset, const std::string& label) {
824 PathBuilder builder;
825 builder.MoveTo({10, 10});
826 builder.LineTo({20, 20});
827 builder.LineTo({20, 10});
828
829 auto verify_path = [](const Path& path, bool is_mutated, bool is_closed,
830 Point offset, const std::string& label) {
831 if (is_mutated) {
832 // We can only test the initial state before the mutator did
833 // its work. We have >= 3 components and the first 3 components
834 // will match what we saw before the mutation.
835 EXPECT_GE(path.GetComponentCount(), 3u) << label;
836 } else {
837 EXPECT_EQ(path.GetComponentCount(), 3u) << label;
838 }
839 {
840 ContourComponent contour;
841 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour)) << label;
842 EXPECT_EQ(contour.destination, offset + Point(10, 10)) << label;
843 EXPECT_EQ(contour.IsClosed(), is_closed) << label;
844 }
845 {
846 LinearPathComponent line;
847 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, line)) << label;
848 EXPECT_EQ(line.p1, offset + Point(10, 10)) << label;
849 EXPECT_EQ(line.p2, offset + Point(20, 20)) << label;
850 }
851 {
852 LinearPathComponent line;
853 EXPECT_TRUE(path.GetLinearComponentAtIndex(2, line)) << label;
854 EXPECT_EQ(line.p1, offset + Point(20, 20)) << label;
855 EXPECT_EQ(line.p2, offset + Point(20, 10)) << label;
856 }
857 };
858
859 auto path1 = builder.CopyPath();
860 verify_path(path1, false, false, {},
861 "Initial Path1 state before " + label);
862
863 for (int i = 0; i < 10; i++) {
864 auto path = builder.CopyPath();
865 verify_path(
866 path, false, false, {},
867 "Extra CopyPath #" + std::to_string(i + 1) + " for " + label);
868 }
869 mutator(builder);
870 verify_path(path1, false, false, {},
871 "Path1 state after subsequent " + label);
872
873 auto path2 = builder.CopyPath();
874 verify_path(path1, false, false, {},
875 "Path1 state after subsequent " + label + " and CopyPath");
876 verify_path(path2, true, will_close, mutation_offset,
877 "Initial Path2 state with subsequent " + label);
878 };
879
880 test_isolation(
881 [](PathBuilder& builder) { //
882 builder.SetConvexity(Convexity::kConvex);
883 },
884 false, {}, "SetConvex");
885
886 test_isolation(
887 [](PathBuilder& builder) { //
888 builder.SetConvexity(Convexity::kUnknown);
889 },
890 false, {}, "SetUnknownConvex");
891
892 test_isolation(
893 [](PathBuilder& builder) { //
894 builder.Close();
895 },
896 true, {}, "Close");
897
898 test_isolation(
899 [](PathBuilder& builder) {
900 builder.MoveTo({20, 30}, false);
901 },
902 false, {}, "Absolute MoveTo");
903
904 test_isolation(
905 [](PathBuilder& builder) {
906 builder.MoveTo({20, 30}, true);
907 },
908 false, {}, "Relative MoveTo");
909
910 test_isolation(
911 [](PathBuilder& builder) {
912 builder.LineTo({20, 30}, false);
913 },
914 false, {}, "Absolute LineTo");
915
916 test_isolation(
917 [](PathBuilder& builder) {
918 builder.LineTo({20, 30}, true);
919 },
920 false, {}, "Relative LineTo");
921
922 test_isolation(
923 [](PathBuilder& builder) { //
924 builder.HorizontalLineTo(100, false);
925 },
926 false, {}, "Absolute HorizontalLineTo");
927
928 test_isolation(
929 [](PathBuilder& builder) { //
930 builder.HorizontalLineTo(100, true);
931 },
932 false, {}, "Relative HorizontalLineTo");
933
934 test_isolation(
935 [](PathBuilder& builder) { //
936 builder.VerticalLineTo(100, false);
937 },
938 false, {}, "Absolute VerticalLineTo");
939
940 test_isolation(
941 [](PathBuilder& builder) { //
942 builder.VerticalLineTo(100, true);
943 },
944 false, {}, "Relative VerticalLineTo");
945
946 test_isolation(
947 [](PathBuilder& builder) {
948 builder.QuadraticCurveTo({20, 30}, {30, 20}, false);
949 },
950 false, {}, "Absolute QuadraticCurveTo");
951
952 test_isolation(
953 [](PathBuilder& builder) {
954 builder.QuadraticCurveTo({20, 30}, {30, 20}, true);
955 },
956 false, {}, "Relative QuadraticCurveTo");
957
958 test_isolation(
959 [](PathBuilder& builder) {
960 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, false);
961 },
962 false, {}, "Absolute CubicCurveTo");
963
964 test_isolation(
965 [](PathBuilder& builder) {
966 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, true);
967 },
968 false, {}, "Relative CubicCurveTo");
969
970 test_isolation(
971 [](PathBuilder& builder) {
972 builder.AddLine({100, 100}, {150, 100});
973 },
974 false, {}, "AddLine");
975
976 test_isolation(
977 [](PathBuilder& builder) {
978 builder.AddRect(Rect::MakeLTRB(100, 100, 120, 120));
979 },
980 false, {}, "AddRect");
981
982 test_isolation(
983 [](PathBuilder& builder) {
984 builder.AddOval(Rect::MakeLTRB(100, 100, 120, 120));
985 },
986 false, {}, "AddOval");
987
988 test_isolation(
989 [](PathBuilder& builder) {
990 builder.AddCircle({100, 100}, 20);
991 },
992 false, {}, "AddCircle");
993
994 test_isolation(
995 [](PathBuilder& builder) {
996 builder.AddArc(Rect::MakeLTRB(100, 100, 120, 120), Degrees(10),
997 Degrees(170));
998 },
999 false, {}, "AddArc");
1000
1001 test_isolation(
1002 [](PathBuilder& builder) {
1003 builder.AddQuadraticCurve({100, 100}, {150, 100}, {150, 150});
1004 },
1005 false, {}, "AddQuadraticCurve");
1006
1007 test_isolation(
1008 [](PathBuilder& builder) {
1009 builder.AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
1010 },
1011 false, {}, "AddCubicCurve");
1012
1013 test_isolation(
1014 [](PathBuilder& builder) {
1015 builder.Shift({23, 42});
1016 },
1017 false, {23, 42}, "Shift");
1018 }

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() [235/465]

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

Definition at line 189 of file path_unittests.cc.

189 {
190 // Closed shapes.
191 {
192 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
193 ContourComponent contour;
194 path.GetContourComponentAtIndex(0, contour);
195 EXPECT_POINT_NEAR(contour.destination, Point(100, 50));
196 EXPECT_TRUE(contour.IsClosed());
197 }
198
199 {
200 Path path =
201 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
202 ContourComponent contour;
203 path.GetContourComponentAtIndex(0, contour);
204 EXPECT_POINT_NEAR(contour.destination, Point(150, 100));
205 EXPECT_TRUE(contour.IsClosed());
206 }
207
208 {
209 Path path =
210 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
211 ContourComponent contour;
212 path.GetContourComponentAtIndex(0, contour);
213 EXPECT_POINT_NEAR(contour.destination, Point(100, 100));
214 EXPECT_TRUE(contour.IsClosed());
215 }
216
217 {
218 Path path = PathBuilder{}
219 .AddRoundRect(RoundRect::MakeRectRadius(
220 Rect::MakeXYWH(100, 100, 100, 100), 10))
221 .TakePath();
222 ContourComponent contour;
223 path.GetContourComponentAtIndex(0, contour);
224 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
225 EXPECT_TRUE(contour.IsClosed());
226 }
227
228 {
229 Path path = PathBuilder{}
230 .AddRoundRect(RoundRect::MakeRectXY(
231 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
232 .TakePath();
233 ContourComponent contour;
234 path.GetContourComponentAtIndex(0, contour);
235 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
236 EXPECT_TRUE(contour.IsClosed());
237 }
238
239 // Open shapes.
240 {
241 Point p(100, 100);
242 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
243 ContourComponent contour;
244 path.GetContourComponentAtIndex(0, contour);
245 ASSERT_POINT_NEAR(contour.destination, p);
246 ASSERT_FALSE(contour.IsClosed());
247 }
248
249 {
250 Path path =
251 PathBuilder{}
252 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
253 .TakePath();
254 ContourComponent contour;
255 path.GetContourComponentAtIndex(0, contour);
256 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
257 ASSERT_FALSE(contour.IsClosed());
258 }
259
260 {
261 Path path = PathBuilder{}
262 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
263 .TakePath();
264 ContourComponent contour;
265 path.GetContourComponentAtIndex(0, contour);
266 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
267 ASSERT_FALSE(contour.IsClosed());
268 }
269 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundRect(), ASSERT_POINT_NEAR, impeller::ContourComponent::destination, EXPECT_POINT_NEAR, impeller::Path::GetContourComponentAtIndex(), impeller::ContourComponent::IsClosed(), impeller::RoundRect::MakeRectRadius(), impeller::RoundRect::MakeRectXY(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [236/465]

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

Definition at line 414 of file path_unittests.cc.

414 {
415 PathBuilder builder;
416 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
417
418 ASSERT_EQ(path_1.GetBoundingBox().value_or(Rect::MakeMaximum()),
419 Rect::MakeLTRB(0, 0, 1, 1));
420
421 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
422
423 // Verify that PathBuilder recomputes the bounds.
424 ASSERT_EQ(path_2.GetBoundingBox().value_or(Rect::MakeMaximum()),
425 Rect::MakeLTRB(-1, -1, 1, 1));
426
427 // PathBuilder can set the bounds to whatever it wants
428 auto path_3 = builder.AddLine({0, 0}, {1, 1})
429 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
430 .TakePath();
431
432 ASSERT_EQ(path_3.GetBoundingBox().value_or(Rect::MakeMaximum()),
433 Rect::MakeLTRB(0, 0, 100, 100));
434 }

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

## ◆ TEST() [237/465]

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

Definition at line 34 of file path_unittests.cc.

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

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

## ◆ TEST() [238/465]

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

Definition at line 271 of file path_unittests.cc.

271 {
272 Path::Polyline polyline = PathBuilder{}
273 .AddLine({100, 100}, {200, 100})
274 .MoveTo({100, 200})
275 .LineTo({150, 250})
276 .LineTo({200, 200})
277 .Close()
278 .TakePath()
279 .CreatePolyline(1.0f);
280 ASSERT_EQ(polyline.points->size(), 6u);
281 ASSERT_EQ(polyline.contours.size(), 2u);
282 ASSERT_EQ(polyline.contours[0].is_closed, false);
283 ASSERT_EQ(polyline.contours[0].start_index, 0u);
284 ASSERT_EQ(polyline.contours[1].is_closed, true);
285 ASSERT_EQ(polyline.contours[1].start_index, 2u);
286 }

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

## ◆ TEST() [239/465]

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

Definition at line 519 of file path_unittests.cc.

519 {
520 PathBuilder builder;
521 // Straight diagonal line.
522 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
523 auto path = builder.TakePath();
524 auto actual = path.GetBoundingBox();
525 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
526
527 ASSERT_TRUE(actual.has_value());
528 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
529 }

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

## ◆ TEST() [240/465]

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

Definition at line 436 of file path_unittests.cc.

436 {
437 PathBuilder builder;
438 auto path = builder.HorizontalLineTo(10).TakePath();
439
440 LinearPathComponent linear;
441 path.GetLinearComponentAtIndex(1, linear);
442
443 EXPECT_EQ(linear.p1, Point(0, 0));
444 EXPECT_EQ(linear.p2, Point(10, 0));
445 }

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

## ◆ TEST() [241/465]

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

Definition at line 322 of file path_unittests.cc.

322 {
323 Path::Polyline polyline =
324 PathBuilder{}
325 .MoveTo({50, 50})
326 .LineTo({50, 50}) // Insert duplicate at beginning of contour.
327 .LineTo({100, 50})
328 .LineTo({100, 50}) // Insert duplicate at contour join.
329 .LineTo({100, 100})
330 .Close() // Implicitly insert duplicate {50, 50} across contours.
331 .LineTo({0, 50})
332 .LineTo({0, 100})
333 .LineTo({0, 100}) // Insert duplicate at end of contour.
334 .TakePath()
335 .CreatePolyline(1.0f);
336 ASSERT_EQ(polyline.contours.size(), 2u);
337 ASSERT_EQ(polyline.contours[0].start_index, 0u);
338 ASSERT_TRUE(polyline.contours[0].is_closed);
339 ASSERT_EQ(polyline.contours[1].start_index, 4u);
340 ASSERT_FALSE(polyline.contours[1].is_closed);
341 ASSERT_EQ(polyline.points->size(), 7u);
342 ASSERT_EQ(polyline.GetPoint(0), Point(50, 50));
343 ASSERT_EQ(polyline.GetPoint(1), Point(100, 50));
344 ASSERT_EQ(polyline.GetPoint(2), Point(100, 100));
345 ASSERT_EQ(polyline.GetPoint(3), Point(50, 50));
346 ASSERT_EQ(polyline.GetPoint(4), Point(50, 50));
347 ASSERT_EQ(polyline.GetPoint(5), Point(0, 50));
348 ASSERT_EQ(polyline.GetPoint(6), Point(0, 100));
349 }

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

## ◆ TEST() [242/465]

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

Definition at line 378 of file path_unittests.cc.

378 {
379 PathBuilder builder{};
380 auto path =
381 builder.AddLine(Point(0, 0), Point(10, 10))
382 .AddQuadraticCurve(Point(10, 10), Point(15, 15), Point(20, 20))
383 .AddCubicCurve(Point(20, 20), Point(25, 25), Point(-5, -5),
384 Point(30, 30))
385 .Close()
386 .Shift(Point(1, 1))
387 .TakePath();
388
389 ContourComponent contour;
390 LinearPathComponent linear;
391 QuadraticPathComponent quad;
392 CubicPathComponent cubic;
393
394 ASSERT_TRUE(path.GetContourComponentAtIndex(0, contour));
395 ASSERT_TRUE(path.GetLinearComponentAtIndex(1, linear));
396 ASSERT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
397 ASSERT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
398
399 EXPECT_EQ(contour.destination, Point(1, 1));
400
401 EXPECT_EQ(linear.p1, Point(1, 1));
402 EXPECT_EQ(linear.p2, Point(11, 11));
403
404 EXPECT_EQ(quad.cp, Point(16, 16));
405 EXPECT_EQ(quad.p1, Point(11, 11));
406 EXPECT_EQ(quad.p2, Point(21, 21));
407
408 EXPECT_EQ(cubic.cp1, Point(26, 26));
409 EXPECT_EQ(cubic.cp2, Point(-4, -4));
410 EXPECT_EQ(cubic.p1, Point(21, 21));
411 EXPECT_EQ(cubic.p2, Point(31, 31));
412 }

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

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

Definition at line 53 of file path_unittests.cc.

53 {
54 // Closed shapes.
55 {
56 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
57 EXPECT_TRUE(path.IsSingleContour());
58 }
59
60 {
61 Path path =
62 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
63
64 EXPECT_TRUE(path.IsSingleContour());
65 }
66
67 {
68 Path path =
69 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
70
71 EXPECT_TRUE(path.IsSingleContour());
72 }
73
74 {
75 Path path = PathBuilder{}
76 .AddRoundRect(RoundRect::MakeRectRadius(
77 Rect::MakeXYWH(100, 100, 100, 100), 10))
78 .TakePath();
79
80 EXPECT_TRUE(path.IsSingleContour());
81 }
82
83 // Open shapes.
84 {
85 Point p(100, 100);
86 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
87
88 EXPECT_TRUE(path.IsSingleContour());
89 }
90
91 {
92 Path path =
93 PathBuilder{}
94 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
95 .TakePath();
96
97 EXPECT_TRUE(path.IsSingleContour());
98 }
99
100 {
101 Path path = PathBuilder{}
102 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
103 .TakePath();
104
105 EXPECT_TRUE(path.IsSingleContour());
106 }
107 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundRect(), impeller::Path::IsSingleContour(), impeller::RoundRect::MakeRectRadius(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [244/465]

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

Definition at line 109 of file path_unittests.cc.

109 {
110 // Closed shapes.
111 {
112 Path path = PathBuilder{}
113 .AddCircle({100, 100}, 50)
114 .AddCircle({100, 100}, 50)
115 .TakePath();
116 EXPECT_FALSE(path.IsSingleContour());
117 }
118
119 {
120 Path path = PathBuilder{}
121 .AddOval(Rect::MakeXYWH(100, 100, 100, 100))
122 .AddOval(Rect::MakeXYWH(100, 100, 100, 100))
123 .TakePath();
124
125 EXPECT_FALSE(path.IsSingleContour());
126 }
127
128 {
129 Path path = PathBuilder{}
130 .AddRect(Rect::MakeXYWH(100, 100, 100, 100))
131 .AddRect(Rect::MakeXYWH(100, 100, 100, 100))
132 .TakePath();
133
134 EXPECT_FALSE(path.IsSingleContour());
135 }
136
137 {
138 Path path = PathBuilder{}
139 .AddRoundRect(RoundRect::MakeRectRadius(
140 Rect::MakeXYWH(100, 100, 100, 100), 10))
141 .AddRoundRect(RoundRect::MakeRectRadius(
142 Rect::MakeXYWH(100, 100, 100, 100), 10))
143 .TakePath();
144
145 EXPECT_FALSE(path.IsSingleContour());
146 }
147
148 {
149 Path path = PathBuilder{}
150 .AddRoundRect(RoundRect::MakeRectXY(
151 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
152 .AddRoundRect(RoundRect::MakeRectXY(
153 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
154 .TakePath();
155
156 EXPECT_FALSE(path.IsSingleContour());
157 }
158
159 // Open shapes.
160 {
161 Point p(100, 100);
162 Path path =
163 PathBuilder{}.AddLine(p, {200, 100}).AddLine(p, {200, 100}).TakePath();
164
165 EXPECT_FALSE(path.IsSingleContour());
166 }
167
168 {
169 Path path =
170 PathBuilder{}
171 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
172 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
173 .TakePath();
174
175 EXPECT_FALSE(path.IsSingleContour());
176 }
177
178 {
179 Path path = PathBuilder{}
180 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
181 .Close()
182 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
183 .TakePath();
184
185 EXPECT_FALSE(path.IsSingleContour());
186 }
187 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundRect(), impeller::Close(), impeller::Path::IsSingleContour(), impeller::RoundRect::MakeRectRadius(), impeller::RoundRect::MakeRectXY(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [245/465]

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

Definition at line 447 of file path_unittests.cc.

447 {
448 PathBuilder builder;
449 auto path = builder.VerticalLineTo(10).TakePath();
450
451 LinearPathComponent linear;
452 path.GetLinearComponentAtIndex(1, linear);
453
454 EXPECT_EQ(linear.p1, Point(0, 0));
455 EXPECT_EQ(linear.p2, Point(0, 10));
456 }

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

## ◆ TEST() [246/465]

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

Definition at line 351 of file path_unittests.cc.

351 {
352 auto point_buffer = std::make_unique<std::vector<Point>>();
353 auto point_buffer_address = reinterpret_cast<uintptr_t>(point_buffer.get());
354 Path::Polyline polyline =
355 PathBuilder{}
356 .MoveTo({50, 50})
357 .LineTo({100, 100})
358 .TakePath()
359 .CreatePolyline(
360 1.0f, std::move(point_buffer),
361 [point_buffer_address](
362 Path::Polyline::PointBufferPtr point_buffer) {
363 ASSERT_EQ(point_buffer->size(), 0u);
364 ASSERT_EQ(point_buffer_address,
365 reinterpret_cast<uintptr_t>(point_buffer.get()));
366 });
367 }

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

## ◆ TEST() [247/465]

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

Definition at line 369 of file path_unittests.cc.

369 {
370 EXPECT_DEATH_IF_SUPPORTED(PathBuilder{}
371 .MoveTo({50, 50})
372 .LineTo({100, 100})
373 .TakePath()
374 .CreatePolyline(1.0f, nullptr),
375 "");
376 }

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

## ◆ TEST() [248/465]

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

Definition at line 288 of file path_unittests.cc.

288 {
289 Path::Polyline polyline = PathBuilder{}
290 .AddLine({100, 100}, {200, 100})
291 .MoveTo({100, 200})
292 .LineTo({150, 250})
293 .LineTo({200, 200})
294 .Close()
295 .TakePath()
296 .CreatePolyline(1.0f);
297 size_t a1, a2, b1, b2;
298 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
299 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
300 ASSERT_EQ(a1, 0u);
301 ASSERT_EQ(a2, 2u);
302 ASSERT_EQ(b1, 2u);
303 ASSERT_EQ(b2, 6u);
304 }

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

## ◆ TEST() [249/465]

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

Definition at line 458 of file path_unittests.cc.

458 {
459 PathBuilder builder;
460 auto path = builder.QuadraticCurveTo(Point(10, 10), Point(20, 20)).TakePath();
461
462 QuadraticPathComponent quad;
463 path.GetQuadraticComponentAtIndex(1, quad);
464
465 EXPECT_EQ(quad.p1, Point(0, 0));
466 EXPECT_EQ(quad.cp, Point(10, 10));
467 EXPECT_EQ(quad.p2, Point(20, 20));
468 }

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

## ◆ TEST() [250/465]

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

Definition at line 622 of file path_unittests.cc.

622 {
623 PathBuilder builder;
624 auto path = builder.LineTo({0, 10})
625 .LineTo({10, 10})
626 .Close() // Returns to (0, 0)
627 .Close() // No Op
628 .Close() // Still No op
629 .TakePath();
630
631 EXPECT_EQ(path.GetComponentCount(), 5u);
632 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 3u);
633 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
634 }

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

## ◆ TEST() [251/465]

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

Definition at line 544 of file path_unittests.cc.

544 {
545 PathBuilder builder;
546
547 auto path = builder.AddLine({0, 0}, {100, 100})
548 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
549 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
550 .TakePath();
551
552 EXPECT_EQ(path.GetComponentCount(), 6u);
553 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
554 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
555 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
556 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 3u);
557
558 {
559 LinearPathComponent linear;
560 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, linear));
561
562 Point p1(0, 0);
563 Point p2(100, 100);
564 EXPECT_EQ(linear.p1, p1);
565 EXPECT_EQ(linear.p2, p2);
566 }
567
568 {
569 QuadraticPathComponent quad;
570 EXPECT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
571
572 Point p1(100, 100);
573 Point cp(200, 200);
574 Point p2(300, 300);
575 EXPECT_EQ(quad.p1, p1);
576 EXPECT_EQ(quad.cp, cp);
577 EXPECT_EQ(quad.p2, p2);
578 }
579
580 {
581 CubicPathComponent cubic;
582 EXPECT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
583
584 Point p1(300, 300);
585 Point cp1(400, 400);
586 Point cp2(500, 500);
587 Point p2(600, 600);
588 EXPECT_EQ(cubic.p1, p1);
589 EXPECT_EQ(cubic.cp1, cp1);
590 EXPECT_EQ(cubic.cp2, cp2);
591 EXPECT_EQ(cubic.p2, p2);
592 }
593
594 {
595 ContourComponent contour;
596 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour));
597
598 Point p1(0, 0);
599 EXPECT_EQ(contour.destination, p1);
600 EXPECT_FALSE(contour.IsClosed());
601 }
602
603 {
604 ContourComponent contour;
605 EXPECT_TRUE(path.GetContourComponentAtIndex(2, contour));
606
607 Point p1(100, 100);
608 EXPECT_EQ(contour.destination, p1);
609 EXPECT_FALSE(contour.IsClosed());
610 }
611
612 {
613 ContourComponent contour;
614 EXPECT_TRUE(path.GetContourComponentAtIndex(4, contour));
615
616 Point p1(300, 300);
617 EXPECT_EQ(contour.destination, p1);
618 EXPECT_FALSE(contour.IsClosed());
619 }
620 }

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

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

Definition at line 784 of file path_unittests.cc.

784 {
785 Path path = PathBuilder{}
786 .AddRoundRect(RoundRect::MakeRectRadius(
787 Rect::MakeLTRB(0, 0, 100, 100), 10))
788 .TakePath();
789 auto [points, contours] = path.CountStorage(1.0);
790
791 std::vector<Point> point_storage(points);
792 std::vector<uint16_t> index_storage(points + (contours - 1));
793
794 StripVertexWriter writer(point_storage.data(), index_storage.data());
795 path.WritePolyline(1.0, writer);
796
797 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
798 EXPECT_EQ(point_storage[0], Point(10, 0));
799 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::StripVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), impeller::PathBuilder::TakePath(), and impeller::Path::WritePolyline().

## ◆ TEST() [253/465]

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

Definition at line 801 of file path_unittests.cc.

801 {
802 PathBuilder builder{};
803 for (auto i = 0; i < 10; i++) {
804 builder.AddRoundRect(
805 RoundRect::MakeRectRadius(Rect::MakeLTRB(0 + i, 0 + i, 100, 100), 10));
806 }
807 auto path = builder.TakePath();
808 auto [points, contours] = path.CountStorage(1.0);
809
810 std::vector<Point> point_storage(points);
811 std::vector<uint16_t> index_storage(points + (contours - 1));
812
813 StripVertexWriter writer(point_storage.data(), index_storage.data());
814 path.WritePolyline(1.0, writer);
815
816 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
817 EXPECT_EQ(point_storage[0], Point(10, 0));
818 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::StripVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [254/465]

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

Definition at line 741 of file path_unittests.cc.

741 {
742 // Create a rectangle that lacks an explicit close.
743 Path path = PathBuilder{}
744 .LineTo({100, 0})
745 .LineTo({100, 100})
746 .LineTo({0, 100})
747 .TakePath();
748
749 std::vector<Point> expected = {{0, 0}, {100, 0}, {100, 100},
750 {0, 100}, {0, 0}, {0, 0}};
751 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 0xFFFF, 0};
752
753 auto [points, contours] = path.CountStorage(1.0);
754
755 std::vector<Point> point_storage(points);
756 std::vector<uint16_t> index_storage(points + (contours - 1));
757
758 StripVertexWriter writer(point_storage.data(), index_storage.data());
759 path.WritePolyline(1.0, writer);
760
761 EXPECT_LE(index_storage, expected_indices);
762 EXPECT_EQ(point_storage, expected);
763 }

References impeller::Path::CountStorage(), impeller::LineTo(), impeller::PathBuilder::LineTo(), and impeller::Path::WritePolyline().

## ◆ TEST() [255/465]

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() [256/465]

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

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

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() [259/465]

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

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

Definition at line 1316 of file rect_unittests.cc.

1316 {
1317 auto rect1 =
1318 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1319 auto rect2 = Rect::MakeXYWH(724.f, 618.f, 600.f, 300.f);
1320 EXPECT_TRUE(rect1.Contains(rect2));
1321 }

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

## ◆ TEST() [261/465]

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

Definition at line 899 of file rect_unittests.cc.

899 {
900 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
901
902 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
903 const std::string& label) {
904 EXPECT_FALSE(IRect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
905 << label << " with Top/Bottom swapped";
906 EXPECT_FALSE(IRect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
907 << label << " with Left/Right swapped";
908 EXPECT_FALSE(IRect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
909 << label << " with all sides swapped";
910 };
911
912 test(20, 20, 30, 30, "Above and Left");
913 test(70, 20, 80, 30, "Above");
914 test(120, 20, 130, 30, "Above and Right");
915 test(120, 70, 130, 80, "Right");
916 test(120, 120, 130, 130, "Below and Right");
917 test(70, 120, 80, 130, "Below");
918 test(20, 120, 30, 130, "Below and Left");
919 test(20, 70, 30, 80, "Left");
920
921 test(70, 70, 80, 80, "Inside");
922
923 test(40, 70, 60, 80, "Straddling Left");
924 test(70, 40, 80, 60, "Straddling Top");
925 test(90, 70, 110, 80, "Straddling Right");
926 test(70, 90, 80, 110, "Straddling Bottom");
927 }

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

## ◆ TEST() [262/465]

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

Definition at line 869 of file rect_unittests.cc.

869 {
870 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
871
872 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
873 const std::string& label) {
874 EXPECT_FALSE(Rect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
875 << label << " with Top/Bottom swapped";
876 EXPECT_FALSE(Rect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
877 << label << " with Left/Right swapped";
878 EXPECT_FALSE(Rect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
879 << label << " with all sides swapped";
880 };
881
882 test(20, 20, 30, 30, "Above and Left");
883 test(70, 20, 80, 30, "Above");
884 test(120, 20, 130, 30, "Above and Right");
885 test(120, 70, 130, 80, "Right");
886 test(120, 120, 130, 130, "Below and Right");
887 test(70, 120, 80, 130, "Below");
888 test(20, 120, 30, 130, "Below and Left");
889 test(20, 70, 30, 80, "Left");
890
891 test(70, 70, 80, 80, "Inside");
892
893 test(40, 70, 60, 80, "Straddling Left");
894 test(70, 40, 80, 60, "Straddling Top");
895 test(90, 70, 110, 80, "Straddling Right");
896 test(70, 90, 80, 110, "Straddling Bottom");
897 }

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

## ◆ TEST() [263/465]

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

Definition at line 1239 of file rect_unittests.cc.

1239 {
1240 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1241 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1242 EXPECT_EQ(Rect::MakeMaximum().GetCenter(), Point(0, 0));
1243
1244 // Note that we expect a Point as the answer from an IRect
1245 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1246 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1247 EXPECT_EQ(IRect::MakeMaximum().GetCenter(), Point(0, 0));
1248 }

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

## ◆ TEST() [264/465]

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

Definition at line 1025 of file rect_unittests.cc.

1025 {
1026 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
1027 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
1028 EXPECT_EQ(IRect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
1029 EXPECT_EQ(IRect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
1030 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
1031 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
1032 }

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

## ◆ TEST() [265/465]

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

Definition at line 2404 of file rect_unittests.cc.

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

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() [266/465]

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

Definition at line 2242 of file rect_unittests.cc.

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

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() [267/465]

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

Definition at line 2595 of file rect_unittests.cc.

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

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() [268/465]

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

Definition at line 686 of file rect_unittests.cc.

686 {
687 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
688 IRect copy = rect;
689
690 EXPECT_EQ(rect, copy);
691 EXPECT_EQ(copy.GetLeft(), 5);
692 EXPECT_EQ(copy.GetTop(), 10);
693 EXPECT_EQ(copy.GetRight(), 20);
694 EXPECT_EQ(copy.GetBottom(), 25);
695 EXPECT_EQ(copy.GetX(), 5);
696 EXPECT_EQ(copy.GetY(), 10);
697 EXPECT_EQ(copy.GetWidth(), 15);
698 EXPECT_EQ(copy.GetHeight(), 15);
699 EXPECT_FALSE(copy.IsEmpty());
700 }

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() [269/465]

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

Definition at line 2840 of file rect_unittests.cc.

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

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

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

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

Definition at line 839 of file rect_unittests.cc.

839 {
840 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
841
842 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
843 const std::string& label) {
844 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(l, b, r, t)))
845 << label << " with Top/Bottom swapped";
846 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, b, l, t)))
847 << label << " with Left/Right swapped";
848 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, t, l, b)))
849 << label << " with all sides swapped";
850 };
851
852 test(20, 20, 30, 30, "Above and Left");
853 test(70, 20, 80, 30, "Above");
854 test(120, 20, 130, 30, "Above and Right");
855 test(120, 70, 130, 80, "Right");
856 test(120, 120, 130, 130, "Below and Right");
857 test(70, 120, 80, 130, "Below");
858 test(20, 120, 30, 130, "Below and Left");
859 test(20, 70, 30, 80, "Left");
860
861 test(70, 70, 80, 80, "Inside");
862
863 test(40, 70, 60, 80, "Straddling Left");
864 test(70, 40, 80, 60, "Straddling Top");
865 test(90, 70, 110, 80, "Straddling Right");
866 test(70, 90, 80, 110, "Straddling Bottom");
867 }

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

## ◆ TEST() [272/465]

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

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

Definition at line 1283 of file rect_unittests.cc.

1283 {
1284 auto rect = IRect::MakeLTRB(100, 100, 200, 200);
1285
1286 // Expand(T amount)
1287 EXPECT_EQ(rect.Expand(10), IRect::MakeLTRB(90, 90, 210, 210));
1288 EXPECT_EQ(rect.Expand(-10), IRect::MakeLTRB(110, 110, 190, 190));
1289
1290 // Expand(amount, amount)
1291 EXPECT_EQ(rect.Expand(10, 10), IRect::MakeLTRB(90, 90, 210, 210));
1292 EXPECT_EQ(rect.Expand(10, -10), IRect::MakeLTRB(90, 110, 210, 190));
1293 EXPECT_EQ(rect.Expand(-10, 10), IRect::MakeLTRB(110, 90, 190, 210));
1294 EXPECT_EQ(rect.Expand(-10, -10), IRect::MakeLTRB(110, 110, 190, 190));
1295
1296 // Expand(amount, amount, amount, amount)
1297 EXPECT_EQ(rect.Expand(10, 20, 30, 40), IRect::MakeLTRB(90, 80, 230, 240));
1298 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), IRect::MakeLTRB(110, 80, 230, 240));
1299 EXPECT_EQ(rect.Expand(10, -20, 30, 40), IRect::MakeLTRB(90, 120, 230, 240));
1300 EXPECT_EQ(rect.Expand(10, 20, -30, 40), IRect::MakeLTRB(90, 80, 170, 240));
1301 EXPECT_EQ(rect.Expand(10, 20, 30, -40), IRect::MakeLTRB(90, 80, 230, 160));
1302
1303 // Expand(IPoint amount)
1304 EXPECT_EQ(rect.Expand(IPoint{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1305 EXPECT_EQ(rect.Expand(IPoint{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1306 EXPECT_EQ(rect.Expand(IPoint{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1307 EXPECT_EQ(rect.Expand(IPoint{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1308
1309 // Expand(ISize amount)
1310 EXPECT_EQ(rect.Expand(ISize{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1311 EXPECT_EQ(rect.Expand(ISize{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1312 EXPECT_EQ(rect.Expand(ISize{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1313 EXPECT_EQ(rect.Expand(ISize{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1314 }

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

## ◆ TEST() [274/465]

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

Definition at line 661 of file rect_unittests.cc.

661 {
662 EXPECT_EQ(IRect(IRect::MakeXYWH(2, 3, 7, 15)), //
663 IRect::MakeXYWH(2, 3, 7, 15));
664 EXPECT_EQ(IRect(IRect::MakeLTRB(2, 3, 7, 15)), //
665 IRect::MakeLTRB(2, 3, 7, 15));
666 }

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

## ◆ TEST() [275/465]

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

Definition at line 1122 of file rect_unittests.cc.

1122 {
1123 {
1124 // Checks for expected matrix values
1125
1126 auto r = IRect::MakeXYWH(100, 200, 200, 400);
1127
1128 EXPECT_EQ(r.GetNormalizingTransform(),
1129 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1130 Matrix::MakeTranslation({-100, -200}));
1131 }
1132
1133 {
1134 // Checks for expected transform of points relative to the rect
1135
1136 auto r = IRect::MakeLTRB(300, 500, 400, 700);
1137 auto m = r.GetNormalizingTransform();
1138
1139 // The 4 corners of the rect => (0, 0) to (1, 1)
1140 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1141 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1142 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1143 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1144
1145 // The center => (0.5, 0.5)
1146 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1147
1148 // Outside the 4 corners => (-1, -1) to (2, 2)
1149 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1150 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1151 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1152 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1153 }
1154
1155 {
1156 // Checks for behavior with empty rects
1157
1158 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1159
1160 // Empty for width and/or height == 0
1161 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1162 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1163 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1164
1165 // Empty for width and/or height < 0
1166 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1167 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1168 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1169 }
1170 }

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

## ◆ TEST() [276/465]

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

Definition at line 1800 of file rect_unittests.cc.

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

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() [277/465]

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

Definition at line 2065 of file rect_unittests.cc.

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

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

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

Definition at line 638 of file rect_unittests.cc.

638 {
639 IRect rect = IRect::MakeMaximum();
640 auto min = std::numeric_limits<int64_t>::min();
641 auto max = std::numeric_limits<int64_t>::max();
642
643 EXPECT_EQ(rect.GetLeft(), min);
644 EXPECT_EQ(rect.GetTop(), min);
645 EXPECT_EQ(rect.GetRight(), max);
646 EXPECT_EQ(rect.GetBottom(), max);
647 EXPECT_EQ(rect.GetX(), min);
648 EXPECT_EQ(rect.GetY(), min);
649 EXPECT_EQ(rect.GetWidth(), max);
650 EXPECT_EQ(rect.GetHeight(), max);
651 EXPECT_FALSE(rect.IsEmpty());
652 }

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() [279/465]

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

Definition at line 728 of file rect_unittests.cc.

728 {
729 {
730 IRect r = IRect::MakeOriginSize({10, 20}, {50, 40});
731 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
732 EXPECT_EQ(r.GetSize(), ISize(50, 40));
733 EXPECT_EQ(r.GetX(), 10);
734 EXPECT_EQ(r.GetY(), 20);
735 EXPECT_EQ(r.GetWidth(), 50);
736 EXPECT_EQ(r.GetHeight(), 40);
737 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
738 EXPECT_EQ(r.GetXYWH(), expected_array);
739 }
740
741 {
742 IRect r = IRect::MakeLTRB(10, 20, 50, 40);
743 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
744 EXPECT_EQ(r.GetSize(), ISize(40, 20));
745 EXPECT_EQ(r.GetX(), 10);
746 EXPECT_EQ(r.GetY(), 20);
747 EXPECT_EQ(r.GetWidth(), 40);
748 EXPECT_EQ(r.GetHeight(), 20);
749 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
750 EXPECT_EQ(r.GetXYWH(), expected_array);
751 }
752 }

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() [280/465]

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

Definition at line 523 of file rect_unittests.cc.

523 {
524 auto min = std::numeric_limits<int64_t>::min();
525 auto max = std::numeric_limits<int64_t>::max();
526
527 // 4 cases
528 // negative l, r near max takes width past max
529 // positive l, r near min takes width below min
530 // negative t, b near max takes width past max
531 // positive t, b near min takes width below min
532
533 {
534 IRect rect = IRect::MakeLTRB(-10, 10, max - 5, 26);
535
536 EXPECT_EQ(rect.GetLeft(), -10);
537 EXPECT_EQ(rect.GetTop(), 10);
538 EXPECT_EQ(rect.GetRight(), max - 5);
539 EXPECT_EQ(rect.GetBottom(), 26);
540 EXPECT_EQ(rect.GetX(), -10);
541 EXPECT_EQ(rect.GetY(), 10);
542 EXPECT_EQ(rect.GetWidth(), max);
543 EXPECT_EQ(rect.GetHeight(), 16);
544 EXPECT_FALSE(rect.IsEmpty());
545 }
546
547 {
548 IRect rect = IRect::MakeLTRB(10, 10, min + 5, 26);
549
550 EXPECT_EQ(rect.GetLeft(), 10);
551 EXPECT_EQ(rect.GetTop(), 10);
552 EXPECT_EQ(rect.GetRight(), min + 5);
553 EXPECT_EQ(rect.GetBottom(), 26);
554 EXPECT_EQ(rect.GetX(), 10);
555 EXPECT_EQ(rect.GetY(), 10);
556 EXPECT_EQ(rect.GetWidth(), min);
557 EXPECT_EQ(rect.GetHeight(), 16);
558 EXPECT_TRUE(rect.IsEmpty());
559 }
560
561 {
562 IRect rect = IRect::MakeLTRB(5, -10, 15, max - 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(), max - 5);
568 EXPECT_EQ(rect.GetX(), 5);
569 EXPECT_EQ(rect.GetY(), -10);
570 EXPECT_EQ(rect.GetWidth(), 10);
571 EXPECT_EQ(rect.GetHeight(), max);
572 EXPECT_FALSE(rect.IsEmpty());
573 }
574
575 {
576 IRect rect = IRect::MakeLTRB(5, 10, 15, min + 5);
577
578 EXPECT_EQ(rect.GetLeft(), 5);
579 EXPECT_EQ(rect.GetTop(), 10);
580 EXPECT_EQ(rect.GetRight(), 15);
581 EXPECT_EQ(rect.GetBottom(), min + 5);
582 EXPECT_EQ(rect.GetX(), 5);
583 EXPECT_EQ(rect.GetY(), 10);
584 EXPECT_EQ(rect.GetWidth(), 10);
585 EXPECT_EQ(rect.GetHeight(), min);
586 EXPECT_TRUE(rect.IsEmpty());
587 }
588 }

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() [281/465]

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

Definition at line 317 of file rect_unittests.cc.

317 {
318 auto min = std::numeric_limits<int64_t>::min();
319 auto max = std::numeric_limits<int64_t>::max();
320
321 // 4 cases
322 // x near max, positive w takes it past max
323 // x near min, negative w takes it below min
324 // y near max, positive h takes it past max
325 // y near min, negative h takes it below min
326
327 {
328 IRect rect = IRect::MakeXYWH(max - 5, 10, 10, 16);
329
330 EXPECT_EQ(rect.GetLeft(), max - 5);
331 EXPECT_EQ(rect.GetTop(), 10);
332 EXPECT_EQ(rect.GetRight(), max);
333 EXPECT_EQ(rect.GetBottom(), 26);
334 EXPECT_EQ(rect.GetX(), max - 5);
335 EXPECT_EQ(rect.GetY(), 10);
336 EXPECT_EQ(rect.GetWidth(), 5);
337 EXPECT_EQ(rect.GetHeight(), 16);
338 EXPECT_FALSE(rect.IsEmpty());
339 }
340
341 {
342 IRect rect = IRect::MakeXYWH(min + 5, 10, -10, 16);
343
344 EXPECT_EQ(rect.GetLeft(), min + 5);
345 EXPECT_EQ(rect.GetTop(), 10);
346 EXPECT_EQ(rect.GetRight(), min);
347 EXPECT_EQ(rect.GetBottom(), 26);
348 EXPECT_EQ(rect.GetX(), min + 5);
349 EXPECT_EQ(rect.GetY(), 10);
350 EXPECT_EQ(rect.GetWidth(), -5);
351 EXPECT_EQ(rect.GetHeight(), 16);
352 EXPECT_TRUE(rect.IsEmpty());
353 }
354
355 {
356 IRect rect = IRect::MakeXYWH(5, max - 10, 10, 16);
357
358 EXPECT_EQ(rect.GetLeft(), 5);
359 EXPECT_EQ(rect.GetTop(), max - 10);
360 EXPECT_EQ(rect.GetRight(), 15);
361 EXPECT_EQ(rect.GetBottom(), max);
362 EXPECT_EQ(rect.GetX(), 5);
363 EXPECT_EQ(rect.GetY(), max - 10);
364 EXPECT_EQ(rect.GetWidth(), 10);
365 EXPECT_EQ(rect.GetHeight(), 10);
366 EXPECT_FALSE(rect.IsEmpty());
367 }
368
369 {
370 IRect rect = IRect::MakeXYWH(5, min + 10, 10, -16);
371
372 EXPECT_EQ(rect.GetLeft(), 5);
373 EXPECT_EQ(rect.GetTop(), min + 10);
374 EXPECT_EQ(rect.GetRight(), 15);
375 EXPECT_EQ(rect.GetBottom(), min);
376 EXPECT_EQ(rect.GetX(), 5);
377 EXPECT_EQ(rect.GetY(), min + 10);
378 EXPECT_EQ(rect.GetWidth(), 10);
379 EXPECT_EQ(rect.GetHeight(), -10);
380 EXPECT_TRUE(rect.IsEmpty());
381 }
382 }

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() [282/465]

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

Definition at line 3098 of file rect_unittests.cc.

3098 {
3099 {
3100 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3101 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3102 EXPECT_EQ(IRect::Round(r), ir);
3103 }
3104 {
3105 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3106 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3107 EXPECT_EQ(IRect::Round(r), ir);
3108 }
3109 {
3110 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3111 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3112 EXPECT_EQ(IRect::Round(r), ir);
3113 }
3114 }

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

## ◆ TEST() [283/465]

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

Definition at line 3070 of file rect_unittests.cc.

3070 {
3071 {
3072 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3073 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3074 EXPECT_EQ(IRect::RoundOut(r), ir);
3075 }
3076 {
3077 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3078 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3079 EXPECT_EQ(IRect::RoundOut(r), ir);
3080 }
3081 }

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

## ◆ TEST() [284/465]

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

Definition at line 974 of file rect_unittests.cc.

974 {
975 auto test1 = [](IRect rect, int64_t scale) {
976 IRect expected = IRect::MakeXYWH(rect.GetX() * scale, //
977 rect.GetY() * scale, //
978 rect.GetWidth() * scale, //
979 rect.GetHeight() * scale);
980
981 EXPECT_EQ(rect.Scale(scale), expected) //
982 << rect << " * " << scale;
983 EXPECT_EQ(rect.Scale(scale, scale), expected) //
984 << rect << " * " << scale;
985 EXPECT_EQ(rect.Scale(IPoint(scale, scale)), expected) //
986 << rect << " * " << scale;
987 EXPECT_EQ(rect.Scale(ISize(scale, scale)), expected) //
988 << rect << " * " << scale;
989 };
990
991 auto test2 = [&test1](IRect rect, int64_t scale_x, int64_t scale_y) {
992 IRect expected = IRect::MakeXYWH(rect.GetX() * scale_x, //
993 rect.GetY() * scale_y, //
994 rect.GetWidth() * scale_x, //
995 rect.GetHeight() * scale_y);
996
997 EXPECT_EQ(rect.Scale(scale_x, scale_y), expected) //
998 << rect << " * " << scale_x << ", " << scale_y;
999 EXPECT_EQ(rect.Scale(IPoint(scale_x, scale_y)), expected) //
1000 << rect << " * " << scale_x << ", " << scale_y;
1001 EXPECT_EQ(rect.Scale(ISize(scale_x, scale_y)), expected) //
1002 << rect << " * " << scale_x << ", " << scale_y;
1003
1004 test1(rect, scale_x);
1005 test1(rect, scale_y);
1006 };
1007
1008 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, 3);
1009 test2(IRect::MakeLTRB(10, 15, 100, 150), 3, 2);
1010 test2(IRect::MakeLTRB(10, 15, -100, 150), 2, 3);
1011 test2(IRect::MakeLTRB(10, 15, 100, -150), 2, 3);
1012 test2(IRect::MakeLTRB(10, 15, 100, 150), -2, 3);
1013 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, -3);
1014 }

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() [285/465]

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

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

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() [288/465]

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

Definition at line 1497 of file rect_unittests.cc.

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

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

## ◆ TEST() [289/465]

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

Definition at line 1196 of file rect_unittests.cc.

1196 {
1197 // Non-empty
1198 EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
1199
1200 // Empty both width and height both 0 or negative, in all combinations
1201 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
1202 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
1203 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
1204 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
1205
1206 // Empty for 0 or negative width or height (but not both at the same time)
1207 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
1208 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
1209 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
1210 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
1211 }

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

## ◆ TEST() [290/465]

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

Definition at line 1227 of file rect_unittests.cc.

1227 {
1228 EXPECT_TRUE(Rect::MakeXYWH(10, 30, 20, 20).IsSquare());
1229 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 20, 19).IsSquare());
1230 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 19, 20).IsSquare());
1231 EXPECT_TRUE(Rect::MakeMaximum().IsSquare());
1232
1233 EXPECT_TRUE(IRect::MakeXYWH(10, 30, 20, 20).IsSquare());
1234 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 20, 19).IsSquare());
1235 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 19, 20).IsSquare());
1236 EXPECT_TRUE(IRect::MakeMaximum().IsSquare());
1237 }

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

## ◆ TEST() [291/465]

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

Definition at line 1213 of file rect_unittests.cc.

1213 {
1214 Quad quad = {
1215 Point(10, 10),
1216 Point(20, 10),
1217 Point(10, 20),
1218 Point(20, 20),
1219 };
1220 std::optional<Rect> bounds = Rect::MakePointBounds(quad);
1221 EXPECT_TRUE(bounds.has_value());
1222 if (bounds.has_value()) {
1223 EXPECT_TRUE(RectNear(bounds.value(), Rect::MakeLTRB(10, 10, 20, 20)));
1224 }
1225 }

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

## ◆ TEST() [292/465]

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

Definition at line 1895 of file rect_unittests.cc.

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

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

## ◆ TEST() [293/465]

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

Definition at line 1569 of file rect_unittests.cc.

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

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

## ◆ TEST() [294/465]

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

Definition at line 1746 of file rect_unittests.cc.

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

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

## ◆ TEST() [295/465]

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

Definition at line 1449 of file rect_unittests.cc.

1449 {
1450 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1451 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1452 auto c = Rect::MakeLTRB(100, 0, 200, 100);
1453
1454 // NullOpt, NullOpt
1455 EXPECT_FALSE(Rect::Union(std::nullopt, std::nullopt).has_value());
1456 EXPECT_EQ(Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1457
1458 auto test1 = [](const Rect& r) {
1459 // Rect, NullOpt
1460 EXPECT_EQ(Rect::Union(r, std::nullopt), r);
1461
1462 // OptRect, NullOpt
1463 EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
1464 EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
1465
1466 // NullOpt, Rect
1467 EXPECT_EQ(Rect::Union(std::nullopt, r), r);
1468
1469 // NullOpt, OptRect
1470 EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
1471 EXPECT_EQ(Rect::Union(std::nullopt, std::optional(r)).value(), r);
1472 };
1473
1474 test1(a);
1475 test1(b);
1476 test1(c);
1477
1478 auto test2 = [](const Rect& a, const Rect& b, const Rect& u) {
1479 ASSERT_EQ(a.Union(b), u);
1480
1481 // Rect, OptRect
1482 EXPECT_EQ(Rect::Union(a, std::optional(b)), u);
1483
1484 // OptRect, Rect
1485 EXPECT_EQ(Rect::Union(std::optional(a), b), u);
1486
1487 // OptRect, OptRect
1488 EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
1489 EXPECT_EQ(Rect::Union(std::optional(a), std::optional(b)).value(), u);
1490 };
1491
1492 test2(a, b, Rect::MakeLTRB(0, 0, 200, 200));
1493 test2(a, c, Rect::MakeLTRB(0, 0, 200, 100));
1494 test2(b, c, Rect::MakeLTRB(100, 0, 200, 200));
1495 }

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

## ◆ TEST() [296/465]

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

Definition at line 1016 of file rect_unittests.cc.

1016 {
1017 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
1018 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
1019 EXPECT_EQ(Rect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
1020 EXPECT_EQ(Rect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
1021 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
1022 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
1023 }

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

## ◆ TEST() [297/465]

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

Definition at line 2311 of file rect_unittests.cc.

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

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

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

Definition at line 2156 of file rect_unittests.cc.

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

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

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

Definition at line 2480 of file rect_unittests.cc.

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

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() [300/465]

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

Definition at line 668 of file rect_unittests.cc.

668 {
669 // Using fractional-power-of-2 friendly values for equality tests
670 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
671 Rect copy = rect;
672
673 EXPECT_EQ(rect, copy);
674 EXPECT_EQ(copy.GetLeft(), 5.125f);
675 EXPECT_EQ(copy.GetTop(), 10.25f);
676 EXPECT_EQ(copy.GetRight(), 20.625f);
677 EXPECT_EQ(copy.GetBottom(), 25.375f);
678 EXPECT_EQ(copy.GetX(), 5.125f);
679 EXPECT_EQ(copy.GetY(), 10.25f);
680 EXPECT_EQ(copy.GetWidth(), 15.5f);
681 EXPECT_EQ(copy.GetHeight(), 15.125f);
682 EXPECT_FALSE(copy.IsEmpty());
683 EXPECT_TRUE(copy.IsFinite());
684 }

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

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

Definition at line 2688 of file rect_unittests.cc.

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

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() [302/465]

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

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

Definition at line 3030 of file rect_unittests.cc.

3030 {
3031 auto r = Rect::MakeLTRB(1, 2, 3, 4);
3032
3033 EXPECT_EQ(r.GetLeft(), 1);
3034 EXPECT_EQ(r.GetTop(), 2);
3035 EXPECT_EQ(r.GetRight(), 3);
3036 EXPECT_EQ(r.GetBottom(), 4);
3037
3038 EXPECT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
3039 EXPECT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
3040 EXPECT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
3041 EXPECT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
3042 }

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

## ◆ TEST() [304/465]

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

Definition at line 809 of file rect_unittests.cc.

809 {
810 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
811
812 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
813 const std::string& label) {
814 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(l, b, r, t)))
815 << label << " with Top/Bottom swapped";
816 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, b, l, t)))
817 << label << " with Left/Right swapped";
818 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, t, l, b)))
819 << label << " with all sides swapped";
820 };
821
822 test(20, 20, 30, 30, "Above and Left");
823 test(70, 20, 80, 30, "Above");
824 test(120, 20, 130, 30, "Above and Right");
825 test(120, 70, 130, 80, "Right");
826 test(120, 120, 130, 130, "Below and Right");
827 test(70, 120, 80, 130, "Below");
828 test(20, 120, 30, 130, "Below and Left");
829 test(20, 70, 30, 80, "Left");
830
831 test(70, 70, 80, 80, "Inside");
832
833 test(40, 70, 60, 80, "Straddling Left");
834 test(70, 40, 80, 60, "Straddling Top");
835 test(90, 70, 110, 80, "Straddling Right");
836 test(70, 90, 80, 110, "Straddling Bottom");
837 }

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

## ◆ TEST() [305/465]

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() [306/465]

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

Definition at line 1250 of file rect_unittests.cc.

1250 {
1251 auto rect = Rect::MakeLTRB(100, 100, 200, 200);
1252
1253 // Expand(T amount)
1254 EXPECT_EQ(rect.Expand(10), Rect::MakeLTRB(90, 90, 210, 210));
1255 EXPECT_EQ(rect.Expand(-10), Rect::MakeLTRB(110, 110, 190, 190));
1256
1257 // Expand(amount, amount)
1258 EXPECT_EQ(rect.Expand(10, 10), Rect::MakeLTRB(90, 90, 210, 210));
1259 EXPECT_EQ(rect.Expand(10, -10), Rect::MakeLTRB(90, 110, 210, 190));
1260 EXPECT_EQ(rect.Expand(-10, 10), Rect::MakeLTRB(110, 90, 190, 210));
1261 EXPECT_EQ(rect.Expand(-10, -10), Rect::MakeLTRB(110, 110, 190, 190));
1262
1263 // Expand(amount, amount, amount, amount)
1264 EXPECT_EQ(rect.Expand(10, 20, 30, 40), Rect::MakeLTRB(90, 80, 230, 240));
1265 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), Rect::MakeLTRB(110, 80, 230, 240));
1266 EXPECT_EQ(rect.Expand(10, -20, 30, 40), Rect::MakeLTRB(90, 120, 230, 240));
1267 EXPECT_EQ(rect.Expand(10, 20, -30, 40), Rect::MakeLTRB(90, 80, 170, 240));
1268 EXPECT_EQ(rect.Expand(10, 20, 30, -40), Rect::MakeLTRB(90, 80, 230, 160));
1269
1270 // Expand(Point amount)
1271 EXPECT_EQ(rect.Expand(Point{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1272 EXPECT_EQ(rect.Expand(Point{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1273 EXPECT_EQ(rect.Expand(Point{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1274 EXPECT_EQ(rect.Expand(Point{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1275
1276 // Expand(Size amount)
1277 EXPECT_EQ(rect.Expand(Size{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1278 EXPECT_EQ(rect.Expand(Size{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1279 EXPECT_EQ(rect.Expand(Size{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1280 EXPECT_EQ(rect.Expand(Size{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1281 }

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

## ◆ TEST() [307/465]

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

Definition at line 164 of file rect_unittests.cc.

164 {
165 IRect irect = IRect::MakeLTRB(10, 20, 30, 40);
166 Rect rect = Rect::Make(irect);
167
168 EXPECT_EQ(rect.GetLeft(), 10);
169 EXPECT_EQ(rect.GetTop(), 20);
170 EXPECT_EQ(rect.GetRight(), 30);
171 EXPECT_EQ(rect.GetBottom(), 40);
172
173 // The following do not compile
174 // IRect irect2 = IRect::Make(rect);
175 // IRect irect2 = IRect::Make(irect);
176 }

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

## ◆ TEST() [308/465]

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

Definition at line 654 of file rect_unittests.cc.

654 {
655 EXPECT_EQ(Rect(Rect::MakeXYWH(2, 3, 7, 15)),
656 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
657 EXPECT_EQ(Rect(Rect::MakeLTRB(2, 3, 7, 15)),
658 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
659 }

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

## ◆ TEST() [309/465]

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

Definition at line 1034 of file rect_unittests.cc.

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

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

## ◆ TEST() [310/465]

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

Definition at line 2959 of file rect_unittests.cc.

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

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

## ◆ TEST() [311/465]

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

Definition at line 3016 of file rect_unittests.cc.

3016 {
3017 {
3018 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
3019 auto actual = r.GetPositive();
3020 EXPECT_RECT_NEAR(r, actual);
3021 }
3022 {
3023 Rect r = Rect::MakeXYWH(100, 200, -100, -100);
3024 auto actual = r.GetPositive();
3025 Rect expected = Rect::MakeXYWH(0, 100, 100, 100);
3026 EXPECT_RECT_NEAR(expected, actual);
3027 }
3028 }

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

## ◆ TEST() [312/465]

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

Definition at line 2990 of file rect_unittests.cc.

2990 {
2991 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2992 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
2993 EXPECT_POINT_NEAR(points[0], Point(110, 220));
2994 EXPECT_POINT_NEAR(points[1], Point(410, 220));
2995 EXPECT_POINT_NEAR(points[2], Point(110, 620));
2996 EXPECT_POINT_NEAR(points[3], Point(410, 620));
2997 }

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

## ◆ TEST() [313/465]

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

Definition at line 1617 of file rect_unittests.cc.

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

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() [314/465]

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

Definition at line 1951 of file rect_unittests.cc.

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

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() [315/465]

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

Definition at line 620 of file rect_unittests.cc.

620 {
621 Rect rect = Rect::MakeMaximum();
622 auto inf = std::numeric_limits<Scalar>::infinity();
623 auto min = std::numeric_limits<Scalar>::lowest();
624 auto max = std::numeric_limits<Scalar>::max();
625
626 EXPECT_EQ(rect.GetLeft(), min);
627 EXPECT_EQ(rect.GetTop(), min);
628 EXPECT_EQ(rect.GetRight(), max);
629 EXPECT_EQ(rect.GetBottom(), max);
630 EXPECT_EQ(rect.GetX(), min);
631 EXPECT_EQ(rect.GetY(), min);
632 EXPECT_EQ(rect.GetWidth(), inf);
633 EXPECT_EQ(rect.GetHeight(), inf);
634 EXPECT_FALSE(rect.IsEmpty());
635 EXPECT_TRUE(rect.IsFinite());
636 }

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() [316/465]

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

Definition at line 2999 of file rect_unittests.cc.

2999 {
3000 {
3001 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
3002 auto r = Rect::MakePointBounds(points.begin(), points.end());
3003 auto expected = Rect::MakeXYWH(0, -1, 4, 7);
3004 EXPECT_TRUE(r.has_value());
3005 if (r.has_value()) {
3006 EXPECT_RECT_NEAR(r.value(), expected);
3007 }
3008 }
3009 {
3010 std::vector<Point> points;
3011 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
3012 EXPECT_FALSE(r.has_value());
3013 }
3014 }

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

## ◆ TEST() [317/465]

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

Definition at line 590 of file rect_unittests.cc.

590 {
591 {
592 Size s(100, 200);
593 Rect r = Rect::MakeSize(s);
594 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
595 EXPECT_RECT_NEAR(r, expected);
596 }
597
598 {
599 ISize s(100, 200);
600 Rect r = Rect::MakeSize(s);
601 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
602 EXPECT_RECT_NEAR(r, expected);
603 }
604
605 {
606 Size s(100, 200);
607 IRect r = IRect::MakeSize(s);
608 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
609 EXPECT_EQ(r, expected);
610 }
611
612 {
613 ISize s(100, 200);
614 IRect r = IRect::MakeSize(s);
615 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
616 EXPECT_EQ(r, expected);
617 }
618 }

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

## ◆ TEST() [318/465]

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

Definition at line 702 of file rect_unittests.cc.

702 {
703 {
704 Rect r = Rect::MakeOriginSize({10, 20}, {50, 40});
705 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
706 EXPECT_EQ(r.GetSize(), Size(50, 40));
707 EXPECT_EQ(r.GetX(), 10);
708 EXPECT_EQ(r.GetY(), 20);
709 EXPECT_EQ(r.GetWidth(), 50);
710 EXPECT_EQ(r.GetHeight(), 40);
711 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
712 EXPECT_EQ(r.GetXYWH(), expected_array);
713 }
714
715 {
716 Rect r = Rect::MakeLTRB(10, 20, 50, 40);
717 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
718 EXPECT_EQ(r.GetSize(), Size(40, 20));
719 EXPECT_EQ(r.GetX(), 10);
720 EXPECT_EQ(r.GetY(), 20);
721 EXPECT_EQ(r.GetWidth(), 40);
722 EXPECT_EQ(r.GetHeight(), 20);
723 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
724 EXPECT_EQ(r.GetXYWH(), expected_array);
725 }
726 }

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() [319/465]

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

Definition at line 384 of file rect_unittests.cc.

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

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() [320/465]

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

Definition at line 178 of file rect_unittests.cc.

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

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() [321/465]

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

Definition at line 3044 of file rect_unittests.cc.

3044 {
3045 {
3046 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
3047 auto actual = r.Project(r);
3048 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
3049 EXPECT_RECT_NEAR(expected, actual);
3050 }
3051 {
3052 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
3053 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
3054 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
3055 EXPECT_RECT_NEAR(expected, actual);
3056 }
3057 }

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

## ◆ TEST() [322/465]

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

Definition at line 3083 of file rect_unittests.cc.

3083 {
3084 {
3085 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3086 EXPECT_EQ(Rect::Round(r), r);
3087 }
3088 {
3089 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3090 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-100, -200, 300, 400));
3091 }
3092 {
3093 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3094 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-101, -201, 301, 401));
3095 }
3096 }

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

## ◆ TEST() [323/465]

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

Definition at line 3059 of file rect_unittests.cc.

3059 {
3060 {
3061 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3062 EXPECT_EQ(Rect::RoundOut(r), r);
3063 }
3064 {
3065 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3066 EXPECT_EQ(Rect::RoundOut(r), Rect::MakeLTRB(-101, -201, 301, 401));
3067 }
3068 }

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

## ◆ TEST() [324/465]

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

Definition at line 754 of file rect_unittests.cc.

754 {
755 Rect rect;
756
757 EXPECT_EQ(Rect::RoundOut(rect), Rect());
758
759 EXPECT_EQ(IRect::RoundOut(rect), IRect());
760 }

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

## ◆ TEST() [325/465]

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

Definition at line 762 of file rect_unittests.cc.

762 {
763 Rect rect = Rect::MakeLTRB(5.125f, 10.75f, 20.625f, 25.375f);
764
765 EXPECT_EQ(Rect::RoundOut(rect), Rect::MakeLTRB(5.0f, 10.0f, 21.0f, 26.0f));
766
767 EXPECT_EQ(IRect::RoundOut(rect), IRect::MakeLTRB(5, 10, 21, 26));
768 }

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

## ◆ TEST() [326/465]

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

Definition at line 770 of file rect_unittests.cc.

770 {
771 auto test = [](int corners) {
772 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
773 Scalar l, t, r, b;
774 int64_t il, it, ir, ib;
775 l = il = 50;
776 t = it = 50;
777 r = ir = 80;
778 b = ib = 80;
779 if ((corners & (1 << 0)) != 0) {
780 l = -1E20;
781 il = std::numeric_limits<int64_t>::min();
782 }
783 if ((corners & (1 << 1)) != 0) {
784 t = -1E20;
785 it = std::numeric_limits<int64_t>::min();
786 }
787 if ((corners & (1 << 2)) != 0) {
788 r = +1E20;
789 ir = std::numeric_limits<int64_t>::max();
790 }
791 if ((corners & (1 << 3)) != 0) {
792 b = +1E20;
793 ib = std::numeric_limits<int64_t>::max();
794 }
795
796 Rect rect = Rect::MakeLTRB(l, t, r, b);
797 IRect irect = IRect::RoundOut(rect);
798 EXPECT_EQ(irect.GetLeft(), il) << corners;
799 EXPECT_EQ(irect.GetTop(), it) << corners;
800 EXPECT_EQ(irect.GetRight(), ir) << corners;
801 EXPECT_EQ(irect.GetBottom(), ib) << corners;
802 };
803
804 for (int corners = 0; corners <= 15; corners++) {
805 test(corners);
806 }
807 }

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() [327/465]

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

Definition at line 929 of file rect_unittests.cc.

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

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() [328/465]

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

Definition at line 2983 of file rect_unittests.cc.

2983 {
2984 auto r = Rect::MakeLTRB(0, 0, 100, 100);
2985
2986 EXPECT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
2987 EXPECT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
2988 }

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

## ◆ TEST() [329/465]

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() [330/465]

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() [331/465]

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() [332/465]

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

Definition at line 1358 of file rect_unittests.cc.

1358 {
1359 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1360 ASSERT_TRUE(a.IsFinite()) << label;
1361 ASSERT_TRUE(b.IsFinite()) << label;
1362 ASSERT_FALSE(a.Union(b).IsEmpty());
1363
1364 for (int i = 1; i < 16; i++) {
1365 // NaN in a produces b
1366 EXPECT_EQ(swap_nan(a, i).Union(b), b) << label << ", index = " << i;
1367 // NaN in b produces a
1368 EXPECT_EQ(a.Union(swap_nan(b, i)), a) << label << ", index = " << i;
1369 // NaN in both is empty
1370 for (int j = 1; j < 16; j++) {
1371 EXPECT_TRUE(swap_nan(a, i).Union(swap_nan(b, j)).IsEmpty())
1372 << label << ", indices = " << i << ", " << j;
1373 }
1374 }
1375 };
1376
1377 auto check_empty_flips = [](const Rect& a, const Rect& b,
1378 const std::string& label) {
1379 ASSERT_FALSE(a.IsEmpty());
1380 // b is allowed to be empty
1381
1382 // unflipped a vs flipped (empty) b yields a
1383 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1384 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1385 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1386
1387 // flipped (empty) a vs unflipped b yields b
1388 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1389 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1390 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1391
1392 // flipped (empty) a vs flipped (empty) b yields empty
1393 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1394 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1395 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1396 };
1397
1398 auto test = [&check_nans, &check_empty_flips](const Rect& a, const Rect& b,
1399 const Rect& result) {
1400 ASSERT_FALSE(a.IsEmpty()) << a;
1401 // b is allowed to be empty
1402
1403 std::stringstream stream;
1404 stream << a << " union " << b;
1405 auto label = stream.str();
1406
1407 EXPECT_EQ(a.Union(b), result) << label;
1408 EXPECT_EQ(b.Union(a), result) << label;
1409 check_empty_flips(a, b, label);
1410 check_nans(a, b, label);
1411 };
1412
1413 {
1414 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1415 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1416 auto expected = Rect::MakeXYWH(100, 100, 100, 100);
1417 test(a, b, expected);
1418 }
1419
1420 {
1421 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1422 auto b = Rect::MakeXYWH(0, 0, 1, 1);
1423 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1424 test(a, b, expected);
1425 }
1426
1427 {
1428 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1429 auto b = Rect::MakeXYWH(10, 10, 1, 1);
1430 auto expected = Rect::MakeXYWH(10, 10, 190, 190);
1431 test(a, b, expected);
1432 }
1433
1434 {
1435 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1436 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1437 auto expected = Rect::MakeXYWH(0, 0, 110, 110);
1438 test(a, b, expected);
1439 }
1440
1441 {
1442 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1443 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1444 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1445 test(a, b, expected);
1446 }
1447 }

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() [333/465]

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

Definition at line 1172 of file rect_unittests.cc.

1172 {
1173 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1174
1175 // Non-empty
1176 EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
1177
1178 // Empty both width and height both 0 or negative, in all combinations
1179 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
1180 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
1181 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
1182 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
1183
1184 // Empty for 0 or negative width or height (but not both at the same time)
1185 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
1186 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
1187 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
1188 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
1189
1190 // Empty for NaN in width or height or both
1191 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
1192 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
1193 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
1194 }

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

## ◆ TEST() [334/465]

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

Definition at line 3116 of file rect_unittests.cc.

3116 {
3117 {
3118 // This matrix should clip no corners.
3119 auto matrix = impeller::Matrix::MakeColumn(
3120 // clang-format off
3121 2.0f, 0.0f, 0.0f, 0.0f,
3122 0.0f, 4.0f, 0.0f, 0.0f,
3123 0.0f, 0.0f, 1.0f, 0.0f,
3124 0.0f, 0.0f, 0.0f, 8.0f
3125 // clang-format on
3126 );
3127 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3128 // None of these should have a W<0
3129 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftTop()),
3130 Vector3(200.0f, 400.0f, 8.0f));
3131 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightTop()),
3132 Vector3(400.0f, 400.0f, 8.0f));
3133 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftBottom()),
3134 Vector3(200.0f, 800.0f, 8.0f));
3135 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightBottom()),
3136 Vector3(400.0f, 800.0f, 8.0f));
3137
3138 Rect expect = Rect::MakeLTRB(25.0f, 50.0f, 50.0f, 100.0f);
3139 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3140 EXPECT_EQ(src.TransformAndClipBounds(matrix), expect);
3141 }
3142
3143 {
3144 // This matrix should clip one corner.
3145 auto matrix = impeller::Matrix::MakeColumn(
3146 // clang-format off
3147 2.0f, 0.0f, 0.0f, -0.01f,
3148 0.0f, 2.0f, 0.0f, -0.006f,
3149 0.0f, 0.0f, 1.0f, 0.0f,
3150 0.0f, 0.0f, 0.0f, 3.0f
3151 // clang-format on
3152 );
3153 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3154 // Exactly one of these should have a W<0
3155 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3156 Vector3(200.0f, 200.0f, 1.4f));
3157 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3158 Vector3(400.0f, 200.0f, 0.4f));
3159 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3160 Vector3(200.0f, 400.0f, 0.8f));
3161 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3162 Vector3(400.0f, 400.0f, -0.2f));
3163
3164 Rect expect = Rect::MakeLTRB(142.85715f, 142.85715f, 6553600.f, 6553600.f);
3165 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3166 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3167 }
3168
3169 {
3170 // This matrix should clip two corners.
3171 auto matrix = impeller::Matrix::MakeColumn(
3172 // clang-format off
3173 2.0f, 0.0f, 0.0f, -.015f,
3174 0.0f, 2.0f, 0.0f, -.006f,
3175 0.0f, 0.0f, 1.0f, 0.0f,
3176 0.0f, 0.0f, 0.0f, 3.0f
3177 // clang-format on
3178 );
3179 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3180 // Exactly two of these should have a W<0
3181 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3182 Vector3(200.0f, 200.0f, 0.9f));
3183 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3184 Vector3(400.0f, 200.0f, -0.6f));
3185 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3186 Vector3(200.0f, 400.0f, 0.3f));
3187 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3188 Vector3(400.0f, 400.0f, -1.2f));
3189
3190 Rect expect = Rect::MakeLTRB(222.2222f, 222.2222f, 5898373.f, 6553600.f);
3191 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3192 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3193 }
3194
3195 {
3196 // This matrix should clip three corners.
3197 auto matrix = impeller::Matrix::MakeColumn(
3198 // clang-format off
3199 2.0f, 0.0f, 0.0f, -.02f,
3200 0.0f, 2.0f, 0.0f, -.006f,
3201 0.0f, 0.0f, 1.0f, 0.0f,
3202 0.0f, 0.0f, 0.0f, 3.0f
3203 // clang-format on
3204 );
3205 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3206 // Exactly three of these should have a W<0
3207 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3208 Vector3(200.0f, 200.0f, 0.4f));
3209 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3210 Vector3(400.0f, 200.0f, -1.6f));
3211 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3212 Vector3(200.0f, 400.0f, -0.2f));
3213 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3214 Vector3(400.0f, 400.0f, -2.2f));
3215
3216 Rect expect = Rect::MakeLTRB(499.99988f, 499.99988f, 5898340.f, 4369400.f);
3217 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3218 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3219 }
3220
3221 {
3222 // This matrix should clip all four corners.
3223 auto matrix = impeller::Matrix::MakeColumn(
3224 // clang-format off
3225 2.0f, 0.0f, 0.0f, -.025f,
3226 0.0f, 2.0f, 0.0f, -.006f,
3227 0.0f, 0.0f, 1.0f, 0.0f,
3228 0.0f, 0.0f, 0.0f, 3.0f
3229 // clang-format on
3230 );
3231 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3232 // All of these should have a W<0
3233 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3234 Vector3(200.0f, 200.0f, -0.1f));
3235 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3236 Vector3(400.0f, 200.0f, -2.6f));
3237 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3238 Vector3(200.0f, 400.0f, -0.7f));
3239 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3240 Vector3(400.0f, 400.0f, -3.2f));
3241
3242 EXPECT_TRUE(src.TransformAndClipBounds(matrix).IsEmpty());
3243 }
3244 }

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() [335/465]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesMSAAResolveWithCorrectStore |
| ) |  |

Definition at line 133 of file render_pass_builder_vk_unittests.cc.

133 {
134 RenderPassBuilderVK builder = RenderPassBuilderVK();
135 auto const context = MockVulkanContextBuilder().Build();
136
137 // Create an MSAA color attachment.
138 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
139 SampleCount::kCount4, LoadAction::kClear,
140 StoreAction::kMultisampleResolve);
141
142 auto render_pass = builder.Build(context->GetDevice());
143
144 EXPECT_TRUE(!!render_pass);
145
146 auto maybe_color = builder.GetColor0();
147 ASSERT_TRUE(maybe_color.has_value());
148 if (!maybe_color.has_value()) {
149 return;
150 }
151 vk::AttachmentDescription color = maybe_color.value();
152
153 // MSAA Texture.
154 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eUndefined);
155 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
156 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
157 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eDontCare);
158
159 auto maybe_resolve = builder.GetColor0Resolve();
160 ASSERT_TRUE(maybe_resolve.has_value());
161 if (!maybe_resolve.has_value()) {
162 return;
163 }
164 vk::AttachmentDescription resolve = maybe_resolve.value();
165
166 // MSAA Resolve Texture.
167 EXPECT_EQ(resolve.initialLayout, vk::ImageLayout::eUndefined);
168 EXPECT_EQ(resolve.finalLayout, vk::ImageLayout::eGeneral);
169 EXPECT_EQ(resolve.loadOp, vk::AttachmentLoadOp::eClear);
170 EXPECT_EQ(resolve.storeOp, vk::AttachmentStoreOp::eStore);
171 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColor0(), impeller::RenderPassBuilderVK::GetColor0Resolve(), impeller::kClear, impeller::kCount4, impeller::kMultisampleResolve, impeller::kR8G8B8A8UNormInt, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [336/465]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithCombinedDepthStencil |
| ) |  |

Definition at line 56 of file render_pass_builder_vk_unittests.cc.

56 {
57 RenderPassBuilderVK builder = RenderPassBuilderVK();
58 auto const context = MockVulkanContextBuilder().Build();
59
60 // Create a single color attachment with a transient depth stencil.
61 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
62 SampleCount::kCount1, LoadAction::kClear,
63 StoreAction::kStore, vk::ImageLayout::eGeneral);
64 builder.SetDepthStencilAttachment(PixelFormat::kD24UnormS8Uint,
65 SampleCount::kCount1, LoadAction::kDontCare,
66 StoreAction::kDontCare);
67
68 auto render_pass = builder.Build(context->GetDevice());
69
70 EXPECT_TRUE(!!render_pass);
71
72 std::optional<vk::AttachmentDescription> maybe_color = builder.GetColor0();
73 ASSERT_TRUE(maybe_color.has_value());
74 if (!maybe_color.has_value()) {
75 return;
76 }
77 vk::AttachmentDescription color = maybe_color.value();
78
79 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eUndefined);
80 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
81 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
82 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eStore);
83
84 std::optional<vk::AttachmentDescription> maybe_depth_stencil =
85 builder.GetDepthStencil();
86 ASSERT_TRUE(maybe_depth_stencil.has_value());
87 if (!maybe_depth_stencil.has_value()) {
88 return;
89 }
90 vk::AttachmentDescription depth_stencil = maybe_depth_stencil.value();
91
92 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
93 EXPECT_EQ(depth_stencil.finalLayout,
94 vk::ImageLayout::eDepthStencilAttachmentOptimal);
95 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
96 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
97 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
98 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
99 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColor0(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kD24UnormS8Uint, impeller::kDontCare, impeller::kR8G8B8A8UNormInt, impeller::kStore, impeller::RenderPassBuilderVK::SetColorAttachment(), and impeller::RenderPassBuilderVK::SetDepthStencilAttachment().

## ◆ TEST() [337/465]

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() [338/465]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithOnlyStencil |
| ) |  |

Definition at line 101 of file render_pass_builder_vk_unittests.cc.

101 {
102 RenderPassBuilderVK builder = RenderPassBuilderVK();
103 auto const context = MockVulkanContextBuilder().Build();
104
105 // Create a single color attachment with a transient depth stencil.
106 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
107 SampleCount::kCount1, LoadAction::kClear,
108 StoreAction::kStore);
109 builder.SetStencilAttachment(PixelFormat::kS8UInt, SampleCount::kCount1,
110 LoadAction::kDontCare, StoreAction::kDontCare);
111
112 auto render_pass = builder.Build(context->GetDevice());
113
114 EXPECT_TRUE(!!render_pass);
115
116 std::optional<vk::AttachmentDescription> maybe_depth_stencil =
117 builder.GetDepthStencil();
118 ASSERT_TRUE(maybe_depth_stencil.has_value());
119 if (!maybe_depth_stencil.has_value()) {
120 return;
121 }
122 vk::AttachmentDescription depth_stencil = maybe_depth_stencil.value();
123
124 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
125 EXPECT_EQ(depth_stencil.finalLayout,
126 vk::ImageLayout::eDepthStencilAttachmentOptimal);
127 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
128 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
129 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
130 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
131 }

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() [339/465]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | RenderPassWithLoadOpUsesCurrentLayout |
| ) |  |

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 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
35 SampleCount::kCount1, LoadAction::kLoad,
36 StoreAction::kStore,
37 vk::ImageLayout::eColorAttachmentOptimal);
38
39 auto render_pass = builder.Build(context->GetDevice());
40
41 EXPECT_TRUE(!!render_pass);
42
43 std::optional<vk::AttachmentDescription> maybe_color = builder.GetColor0();
44 ASSERT_TRUE(maybe_color.has_value());
45 if (!maybe_color.has_value()) {
46 return;
47 }
48 vk::AttachmentDescription color = maybe_color.value();
49
50 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eColorAttachmentOptimal);
51 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
52 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eLoad);
53 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eStore);
54 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColor0(), impeller::kCount1, impeller::kLoad, impeller::kR8G8B8A8UNormInt, impeller::kStore, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [340/465]

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() [341/465]

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() [342/465]

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() [343/465]

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() [344/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractAndRequireRadiiAdjustment |
| ) |  |

Definition at line 802 of file round_rect_unittests.cc.

802 {
803 RoundRect round_rect =
804 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
805 {
806 .top_left = Size(1.0f, 2.0f),
807 .top_right = Size(3.0f, 4.0f),
808 .bottom_left = Size(5.0f, 6.0f),
809 .bottom_right = Size(7.0f, 8.0f),
810 });
811 RoundRect expanded = round_rect.Expand(-12.0);
812 // Largest sum of paired radii sizes are the bottom and right edges
813 // both of which sum to 12
814 // Rect was 30x30 reduced by 12 on all sides leaving only 6x6, so all
815 // radii are scaled by half to avoid overflowing the contracted rect
816
817 EXPECT_FALSE(expanded.IsEmpty());
818 EXPECT_FALSE(expanded.IsRect());
819 EXPECT_FALSE(expanded.IsOval());
820 EXPECT_TRUE(expanded.IsFinite());
821 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
822 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(22.0f, 22.0f, 28.0f, 28.0f));
823 EXPECT_EQ(expanded.GetRadii().top_left, Size(0.5f, 1.0f));
824 EXPECT_EQ(expanded.GetRadii().top_right, Size(1.5f, 2.0f));
825 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(2.5f, 3.0f));
826 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(3.5f, 4.0f));
827
828 // In this test, the MakeRectRadii constructor will make the same
829 // adjustment to the radii that the Expand method applied.
830 EXPECT_EQ(expanded,
831 RoundRect::MakeRectRadii(Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
832 {
833 .top_left = Size(1.0f, 2.0f),
834 .top_right = Size(3.0f, 4.0f),
835 .bottom_left = Size(5.0f, 6.0f),
836 .bottom_right = Size(7.0f, 8.0f),
837 }));
838
839 // In this test, the arguments to the constructor supply the correctly
840 // adjusted radii (though there is no real way to tell other than
841 // the result is the same).
842 EXPECT_EQ(expanded,
843 RoundRect::MakeRectRadii(Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
844 {
845 .top_left = Size(0.5f, 1.0f),
846 .top_right = Size(1.5f, 2.0f),
847 .bottom_left = Size(2.5f, 3.0f),
848 .bottom_right = Size(3.5f, 4.0f),
849 }));
850 }

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

## ◆ TEST() [345/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractFourScalars |
| ) |  |

Definition at line 770 of file round_rect_unittests.cc.

770 {
771 RoundRect round_rect =
772 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
773 {
774 .top_left = Size(1.0f, 2.0f),
775 .top_right = Size(3.0f, 4.0f),
776 .bottom_left = Size(5.0f, 6.0f),
777 .bottom_right = Size(7.0f, 8.0f),
778 });
779 RoundRect expanded = round_rect.Expand(-1.0, -1.5, -2.0, -2.5);
780
781 EXPECT_FALSE(expanded.IsEmpty());
782 EXPECT_FALSE(expanded.IsRect());
783 EXPECT_FALSE(expanded.IsOval());
784 EXPECT_TRUE(expanded.IsFinite());
785 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
786 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 11.5f, 38.0f, 37.5f));
787 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
788 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
789 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
790 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
791
792 EXPECT_EQ(expanded,
793 RoundRect::MakeRectRadii(Rect::MakeXYWH(11.0f, 11.5f, 27.0f, 26.0f),
794 {
795 .top_left = Size(1.0f, 2.0f),
796 .top_right = Size(3.0f, 4.0f),
797 .bottom_left = Size(5.0f, 6.0f),
798 .bottom_right = Size(7.0f, 8.0f),
799 }));
800 }

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

## ◆ TEST() [346/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractScalar |
| ) |  |

Definition at line 706 of file round_rect_unittests.cc.

706 {
707 RoundRect round_rect =
708 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
709 {
710 .top_left = Size(1.0f, 2.0f),
711 .top_right = Size(3.0f, 4.0f),
712 .bottom_left = Size(5.0f, 6.0f),
713 .bottom_right = Size(7.0f, 8.0f),
714 });
715 RoundRect expanded = round_rect.Expand(-2.0);
716
717 EXPECT_FALSE(expanded.IsEmpty());
718 EXPECT_FALSE(expanded.IsRect());
719 EXPECT_FALSE(expanded.IsOval());
720 EXPECT_TRUE(expanded.IsFinite());
721 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
722 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(12.0f, 12.0f, 38.0f, 38.0f));
723 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
724 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
725 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
726 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
727
728 EXPECT_EQ(expanded,
729 RoundRect::MakeRectRadii(Rect::MakeXYWH(12.0f, 12.0f, 26.0f, 26.0f),
730 {
731 .top_left = Size(1.0f, 2.0f),
732 .top_right = Size(3.0f, 4.0f),
733 .bottom_left = Size(5.0f, 6.0f),
734 .bottom_right = Size(7.0f, 8.0f),
735 }));
736 }

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

## ◆ TEST() [347/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractTwoScalars |
| ) |  |

Definition at line 738 of file round_rect_unittests.cc.

738 {
739 RoundRect round_rect =
740 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
741 {
742 .top_left = Size(1.0f, 2.0f),
743 .top_right = Size(3.0f, 4.0f),
744 .bottom_left = Size(5.0f, 6.0f),
745 .bottom_right = Size(7.0f, 8.0f),
746 });
747 RoundRect expanded = round_rect.Expand(-1.0, -2.0);
748
749 EXPECT_FALSE(expanded.IsEmpty());
750 EXPECT_FALSE(expanded.IsRect());
751 EXPECT_FALSE(expanded.IsOval());
752 EXPECT_TRUE(expanded.IsFinite());
753 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
754 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 12.0f, 39.0f, 38.0f));
755 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
756 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
757 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
758 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
759
760 EXPECT_EQ(expanded,
761 RoundRect::MakeRectRadii(Rect::MakeXYWH(11.0f, 12.0f, 28.0f, 26.0f),
762 {
763 .top_left = Size(1.0f, 2.0f),
764 .top_right = Size(3.0f, 4.0f),
765 .bottom_left = Size(5.0f, 6.0f),
766 .bottom_right = Size(7.0f, 8.0f),
767 }));
768 }

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

## ◆ TEST() [348/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | DefaultConstructor |
| ) |  |

Definition at line 347 of file round_rect_unittests.cc.

347 {
348 RoundRect round_rect = RoundRect();
349
350 EXPECT_TRUE(round_rect.IsEmpty());
351 EXPECT_FALSE(round_rect.IsRect());
352 EXPECT_FALSE(round_rect.IsOval());
353 EXPECT_TRUE(round_rect.IsFinite());
354 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
355 EXPECT_EQ(round_rect.GetBounds(), Rect());
356 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
357 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
358 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
359 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
360 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [349/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | DifferingCornersRoundRectContains |
| ) |  |

Definition at line 958 of file round_rect_unittests.cc.

958 {
959 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
960 auto round_rect =
961 RoundRect::MakeRectRadii(bounds, {
962 .top_left = Size(2.0, 3.0),
963 .top_right = Size(4.0, 5.0),
964 .bottom_left = Size(6.0, 7.0),
965 .bottom_right = Size(8.0, 9.0),
966 });
967
968 // For a corner with radii {A, B}, the "45 degree point" on the
969 // corner curve will be at an offset of:
970 //
971 // (A * sqrt(2) / 2, B * sqrt(2) / 2)
972 //
973 // And the center(s) of these corners are at:
974 //
975 // (+/-(50 - A), +/-(50 - B))
976 auto coord = [](Scalar radius) {
977 return 50 - radius + radius * kSqrt2 / 2.0f - kEhCloseEnough;
978 };
979 auto coord_in = [&coord](Scalar radius) {
980 return coord(radius) - kEhCloseEnough;
981 };
982 auto coord_out = [&coord](Scalar radius) {
983 // For some reason 1 kEhCloseEnough is not enough to put us outside
984 // in some of the cases, so we use 2x the epsilon.
985 return coord(radius) + 2 * kEhCloseEnough;
986 };
987 // Upper left corner (radii = {2.0, 3.0})
988 EXPECT_TRUE(round_rect.Contains({-coord_in(2.0), -coord_in(3.0)}));
989 EXPECT_FALSE(round_rect.Contains({-coord_out(2.0), -coord_out(3.0)}));
990 // Upper right corner (radii = {4.0, 5.0})
991 EXPECT_TRUE(round_rect.Contains({coord_in(4.0), -coord_in(5.0)}));
992 EXPECT_FALSE(round_rect.Contains({coord_out(4.0), -coord_out(5.0)}));
993 // Lower left corner (radii = {6.0, 7.0})
994 EXPECT_TRUE(round_rect.Contains({-coord_in(6.0), coord_in(7.0)}));
995 EXPECT_FALSE(round_rect.Contains({-coord_out(6.0), coord_out(7.0)}));
996 // Lower right corner (radii = {8.0, 9.0})
997 EXPECT_TRUE(round_rect.Contains({coord_in(8.0), coord_in(9.0)}));
998 EXPECT_FALSE(round_rect.Contains({coord_out(8.0), coord_out(9.0)}));
999 }

References impeller::kEhCloseEnough, impeller::kSqrt2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectRadii().

## ◆ TEST() [350/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | EmptyDeclaration |
| ) |  |

Definition at line 320 of file round_rect_unittests.cc.

320 {
321 RoundRect round_rect;
322
323 EXPECT_TRUE(round_rect.IsEmpty());
324 EXPECT_FALSE(round_rect.IsRect());
325 EXPECT_FALSE(round_rect.IsOval());
326 EXPECT_TRUE(round_rect.IsFinite());
327 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
328 EXPECT_EQ(round_rect.GetBounds(), Rect());
329 EXPECT_EQ(round_rect.GetBounds().GetLeft(), 0.0f);
330 EXPECT_EQ(round_rect.GetBounds().GetTop(), 0.0f);
331 EXPECT_EQ(round_rect.GetBounds().GetRight(), 0.0f);
332 EXPECT_EQ(round_rect.GetBounds().GetBottom(), 0.0f);
333 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
334 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
335 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
336 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
337 EXPECT_EQ(round_rect.GetRadii().top_left.width, 0.0f);
338 EXPECT_EQ(round_rect.GetRadii().top_left.height, 0.0f);
339 EXPECT_EQ(round_rect.GetRadii().top_right.width, 0.0f);
340 EXPECT_EQ(round_rect.GetRadii().top_right.height, 0.0f);
341 EXPECT_EQ(round_rect.GetRadii().bottom_left.width, 0.0f);
342 EXPECT_EQ(round_rect.GetRadii().bottom_left.height, 0.0f);
343 EXPECT_EQ(round_rect.GetRadii().bottom_right.width, 0.0f);
344 EXPECT_EQ(round_rect.GetRadii().bottom_right.height, 0.0f);
345 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TRect< T >::GetBottom(), impeller::RoundRect::GetBounds(), impeller::TRect< T >::GetLeft(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TSize< T >::height, impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [351/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | EmptyOvalConstruction |
| ) |  |

Definition at line 410 of file round_rect_unittests.cc.

410 {
411 RoundRect round_rect = RoundRect::MakeRectXY(
412 Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f), 10.0f, 10.0f);
413
414 EXPECT_TRUE(round_rect.IsEmpty());
415 EXPECT_FALSE(round_rect.IsRect());
416 EXPECT_FALSE(round_rect.IsOval());
417 EXPECT_TRUE(round_rect.IsFinite());
418 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
419 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
420 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
421 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
422 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
423 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
424 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [352/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | EmptyRectConstruction |
| ) |  |

Definition at line 362 of file round_rect_unittests.cc.

362 {
363 RoundRect round_rect =
364 RoundRect::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
365
366 EXPECT_TRUE(round_rect.IsEmpty());
367 EXPECT_FALSE(round_rect.IsRect());
368 EXPECT_FALSE(round_rect.IsOval());
369 EXPECT_TRUE(round_rect.IsFinite());
370 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
371 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
372 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
373 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
374 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
375 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
376 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [353/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ExpandFourScalars |
| ) |  |

Definition at line 674 of file round_rect_unittests.cc.

674 {
675 RoundRect round_rect =
676 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
677 {
678 .top_left = Size(1.0f, 2.0f),
679 .top_right = Size(3.0f, 4.0f),
680 .bottom_left = Size(5.0f, 6.0f),
681 .bottom_right = Size(7.0f, 8.0f),
682 });
683 RoundRect expanded = round_rect.Expand(5.0, 6.0, 7.0, 8.0);
684
685 EXPECT_FALSE(expanded.IsEmpty());
686 EXPECT_FALSE(expanded.IsRect());
687 EXPECT_FALSE(expanded.IsOval());
688 EXPECT_TRUE(expanded.IsFinite());
689 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
690 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 47.0f, 48.0f));
691 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
692 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
693 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
694 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
695
696 EXPECT_EQ(expanded,
697 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 4.0f, 42.0f, 44.0f),
698 {
699 .top_left = Size(1.0f, 2.0f),
700 .top_right = Size(3.0f, 4.0f),
701 .bottom_left = Size(5.0f, 6.0f),
702 .bottom_right = Size(7.0f, 8.0f),
703 }));
704 }

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

## ◆ TEST() [354/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ExpandScalar |
| ) |  |

Definition at line 610 of file round_rect_unittests.cc.

610 {
611 RoundRect round_rect =
612 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
613 {
614 .top_left = Size(1.0f, 2.0f),
615 .top_right = Size(3.0f, 4.0f),
616 .bottom_left = Size(5.0f, 6.0f),
617 .bottom_right = Size(7.0f, 8.0f),
618 });
619 RoundRect expanded = round_rect.Expand(5.0);
620
621 EXPECT_FALSE(expanded.IsEmpty());
622 EXPECT_FALSE(expanded.IsRect());
623 EXPECT_FALSE(expanded.IsOval());
624 EXPECT_TRUE(expanded.IsFinite());
625 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
626 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 5.0f, 45.0f, 45.0f));
627 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
628 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
629 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
630 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
631
632 EXPECT_EQ(expanded,
633 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 5.0f, 40.0f, 40.0f),
634 {
635 .top_left = Size(1.0f, 2.0f),
636 .top_right = Size(3.0f, 4.0f),
637 .bottom_left = Size(5.0f, 6.0f),
638 .bottom_right = Size(7.0f, 8.0f),
639 }));
640 }

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

## ◆ TEST() [355/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ExpandTwoScalars |
| ) |  |

Definition at line 642 of file round_rect_unittests.cc.

642 {
643 RoundRect round_rect =
644 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
645 {
646 .top_left = Size(1.0f, 2.0f),
647 .top_right = Size(3.0f, 4.0f),
648 .bottom_left = Size(5.0f, 6.0f),
649 .bottom_right = Size(7.0f, 8.0f),
650 });
651 RoundRect expanded = round_rect.Expand(5.0, 6.0);
652
653 EXPECT_FALSE(expanded.IsEmpty());
654 EXPECT_FALSE(expanded.IsRect());
655 EXPECT_FALSE(expanded.IsOval());
656 EXPECT_TRUE(expanded.IsFinite());
657 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
658 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 45.0f, 46.0f));
659 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
660 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
661 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
662 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
663
664 EXPECT_EQ(expanded,
665 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 4.0f, 40.0f, 42.0f),
666 {
667 .top_left = Size(1.0f, 2.0f),
668 .top_right = Size(3.0f, 4.0f),
669 .bottom_left = Size(5.0f, 6.0f),
670 .bottom_right = Size(7.0f, 8.0f),
671 }));
672 }

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

## ◆ TEST() [356/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | InvertedOvalConstruction |
| ) |  |

Definition at line 442 of file round_rect_unittests.cc.

442 {
443 RoundRect round_rect = RoundRect::MakeRectXY(
444 Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f), 10.0f, 10.0f);
445
446 EXPECT_FALSE(round_rect.IsEmpty());
447 EXPECT_FALSE(round_rect.IsRect());
448 EXPECT_TRUE(round_rect.IsOval());
449 EXPECT_TRUE(round_rect.IsFinite());
450 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
451 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
452 EXPECT_EQ(round_rect.GetRadii().top_left, Size(5.0f, 5.0f));
453 EXPECT_EQ(round_rect.GetRadii().top_right, Size(5.0f, 5.0f));
454 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(5.0f, 5.0f));
455 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(5.0f, 5.0f));
456 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [357/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | InvertedRectConstruction |
| ) |  |

Definition at line 394 of file round_rect_unittests.cc.

394 {
395 RoundRect round_rect =
396 RoundRect::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f));
397
398 EXPECT_FALSE(round_rect.IsEmpty());
399 EXPECT_TRUE(round_rect.IsRect());
400 EXPECT_FALSE(round_rect.IsOval());
401 EXPECT_TRUE(round_rect.IsFinite());
402 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
403 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
404 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
405 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
406 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
407 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
408 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [358/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | NoCornerRoundRectContains |
| ) |  |

Definition at line 852 of file round_rect_unittests.cc.

852 {
853 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
854 // RRect of bounds with no corners contains corners just barely
855 auto no_corners = RoundRect::MakeRectXY(bounds, 0.0f, 0.0f);
856
857 EXPECT_TRUE(no_corners.Contains({-50, -50}));
858 // Rectangles have half-in, half-out containment so we need
859 // to be careful about testing containment of right/bottom corners.
860 EXPECT_TRUE(no_corners.Contains({-50, 49.99}));
861 EXPECT_TRUE(no_corners.Contains({49.99, -50}));
862 EXPECT_TRUE(no_corners.Contains({49.99, 49.99}));
863 EXPECT_FALSE(no_corners.Contains({-50.01, -50}));
864 EXPECT_FALSE(no_corners.Contains({-50, -50.01}));
865 EXPECT_FALSE(no_corners.Contains({-50.01, 50}));
866 EXPECT_FALSE(no_corners.Contains({-50, 50.01}));
867 EXPECT_FALSE(no_corners.Contains({50.01, -50}));
868 EXPECT_FALSE(no_corners.Contains({50, -50.01}));
869 EXPECT_FALSE(no_corners.Contains({50.01, 50}));
870 EXPECT_FALSE(no_corners.Contains({50, 50.01}));
871 }

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

## ◆ TEST() [359/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | OvalConstructor |
| ) |  |

Definition at line 426 of file round_rect_unittests.cc.

426 {
427 RoundRect round_rect =
428 RoundRect::MakeOval(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
429
430 EXPECT_FALSE(round_rect.IsEmpty());
431 EXPECT_FALSE(round_rect.IsRect());
432 EXPECT_TRUE(round_rect.IsOval());
433 EXPECT_TRUE(round_rect.IsFinite());
434 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
435 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
436 EXPECT_EQ(round_rect.GetRadii().top_left, Size(5.0f, 5.0f));
437 EXPECT_EQ(round_rect.GetRadii().top_right, Size(5.0f, 5.0f));
438 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(5.0f, 5.0f));
439 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(5.0f, 5.0f));
440 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeOval(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [360/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectConstructor |
| ) |  |

Definition at line 378 of file round_rect_unittests.cc.

378 {
379 RoundRect round_rect =
380 RoundRect::MakeRect(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
381
382 EXPECT_FALSE(round_rect.IsEmpty());
383 EXPECT_TRUE(round_rect.IsRect());
384 EXPECT_FALSE(round_rect.IsOval());
385 EXPECT_TRUE(round_rect.IsFinite());
386 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
387 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
388 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
389 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
390 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
391 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
392 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [361/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiiConstructor |
| ) |  |

Definition at line 506 of file round_rect_unittests.cc.

506 {
507 RoundRect round_rect =
508 RoundRect::MakeRectRadii(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
509 {
510 .top_left = Size(1.0, 1.5),
511 .top_right = Size(2.0, 2.5f),
512 .bottom_left = Size(3.0, 3.5f),
513 .bottom_right = Size(4.0, 4.5f),
514 });
515
516 EXPECT_FALSE(round_rect.IsEmpty());
517 EXPECT_FALSE(round_rect.IsRect());
518 EXPECT_FALSE(round_rect.IsOval());
519 EXPECT_TRUE(round_rect.IsFinite());
520 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
521 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
522 EXPECT_EQ(round_rect.GetRadii().top_left, Size(1.0f, 1.5f));
523 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 2.5f));
524 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(3.0f, 3.5f));
525 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(4.0f, 4.5f));
526 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [362/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiiOverflowHeightConstructor |
| ) |  |

Definition at line 553 of file round_rect_unittests.cc.

553 {
554 RoundRect round_rect =
555 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 6.0f),
556 {
557 .top_left = Size(1.0f, 2.0f),
558 .top_right = Size(3.0f, 4.0f),
559 .bottom_left = Size(5.0f, 6.0f),
560 .bottom_right = Size(7.0f, 8.0f),
561 });
562 // Largest sum of paired radii heights is the right edge which sums to 12
563 // Rect is only 6 tall so all radii are scaled by half
564 // Rect is 30 wide so no scaling should happen due to radii widths
565
566 EXPECT_FALSE(round_rect.IsEmpty());
567 EXPECT_FALSE(round_rect.IsRect());
568 EXPECT_FALSE(round_rect.IsOval());
569 EXPECT_TRUE(round_rect.IsFinite());
570 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
571 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 40.0f, 16.0f));
572 EXPECT_EQ(round_rect.GetRadii().top_left, Size(0.5f, 1.0f));
573 EXPECT_EQ(round_rect.GetRadii().top_right, Size(1.5f, 2.0f));
574 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.5f, 3.0f));
575 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(3.5f, 4.0f));
576 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [363/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiiOverflowWidthConstructor |
| ) |  |

Definition at line 528 of file round_rect_unittests.cc.

528 {
529 RoundRect round_rect =
530 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 6.0f, 30.0f),
531 {
532 .top_left = Size(1.0f, 2.0f),
533 .top_right = Size(3.0f, 4.0f),
534 .bottom_left = Size(5.0f, 6.0f),
535 .bottom_right = Size(7.0f, 8.0f),
536 });
537 // Largest sum of paired radii widths is the bottom edge which sums to 12
538 // Rect is only 6 wide so all radii are scaled by half
539 // Rect is 30 tall so no scaling should happen due to radii heights
540
541 EXPECT_FALSE(round_rect.IsEmpty());
542 EXPECT_FALSE(round_rect.IsRect());
543 EXPECT_FALSE(round_rect.IsOval());
544 EXPECT_TRUE(round_rect.IsFinite());
545 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
546 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 16.0f, 40.0f));
547 EXPECT_EQ(round_rect.GetRadii().top_left, Size(0.5f, 1.0f));
548 EXPECT_EQ(round_rect.GetRadii().top_right, Size(1.5f, 2.0f));
549 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.5f, 3.0f));
550 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(3.5f, 4.0f));
551 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [364/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiusConstructor |
| ) |  |

Definition at line 458 of file round_rect_unittests.cc.

458 {
459 RoundRect round_rect = RoundRect::MakeRectRadius(
460 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f);
461
462 EXPECT_FALSE(round_rect.IsEmpty());
463 EXPECT_FALSE(round_rect.IsRect());
464 EXPECT_FALSE(round_rect.IsOval());
465 EXPECT_TRUE(round_rect.IsFinite());
466 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
467 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
468 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 2.0f));
469 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 2.0f));
470 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 2.0f));
471 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 2.0f));
472 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [365/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectSizeConstructor |
| ) |  |

Definition at line 490 of file round_rect_unittests.cc.

490 {
491 RoundRect round_rect = RoundRect::MakeRectXY(
492 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), Size(2.0f, 3.0f));
493
494 EXPECT_FALSE(round_rect.IsEmpty());
495 EXPECT_FALSE(round_rect.IsRect());
496 EXPECT_FALSE(round_rect.IsOval());
497 EXPECT_TRUE(round_rect.IsFinite());
498 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
499 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
500 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 3.0f));
501 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 3.0f));
502 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 3.0f));
503 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 3.0f));
504 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [366/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectXYConstructor |
| ) |  |

Definition at line 474 of file round_rect_unittests.cc.

474 {
475 RoundRect round_rect = RoundRect::MakeRectXY(
476 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f, 3.0f);
477
478 EXPECT_FALSE(round_rect.IsEmpty());
479 EXPECT_FALSE(round_rect.IsRect());
480 EXPECT_FALSE(round_rect.IsOval());
481 EXPECT_TRUE(round_rect.IsFinite());
482 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
483 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
484 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 3.0f));
485 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 3.0f));
486 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 3.0f));
487 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 3.0f));
488 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::RoundRect::IsEmpty(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [367/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiCornersSameTolerance |
| ) |  |

Definition at line 268 of file round_rect_unittests.cc.

268 {
269 RoundingRadii radii{
270 .top_left = {10, 20},
271 .top_right = {10.01, 20.01},
272 .bottom_left = {9.99, 19.99},
273 .bottom_right = {9.99, 20.01},
274 };
275
276 EXPECT_TRUE(radii.AreAllCornersSame(.02));
277
278 {
279 RoundingRadii different = radii;
280 different.top_left.width = 10.03;
281 EXPECT_FALSE(different.AreAllCornersSame(.02));
282 }
283 {
284 RoundingRadii different = radii;
285 different.top_left.height = 20.03;
286 EXPECT_FALSE(different.AreAllCornersSame(.02));
287 }
288 {
289 RoundingRadii different = radii;
290 different.top_right.width = 10.03;
291 EXPECT_FALSE(different.AreAllCornersSame(.02));
292 }
293 {
294 RoundingRadii different = radii;
295 different.top_right.height = 20.03;
296 EXPECT_FALSE(different.AreAllCornersSame(.02));
297 }
298 {
299 RoundingRadii different = radii;
300 different.bottom_left.width = 9.97;
301 EXPECT_FALSE(different.AreAllCornersSame(.02));
302 }
303 {
304 RoundingRadii different = radii;
305 different.bottom_left.height = 19.97;
306 EXPECT_FALSE(different.AreAllCornersSame(.02));
307 }
308 {
309 RoundingRadii different = radii;
310 different.bottom_right.width = 9.97;
311 EXPECT_FALSE(different.AreAllCornersSame(.02));
312 }
313 {
314 RoundingRadii different = radii;
315 different.bottom_right.height = 20.03;
316 EXPECT_FALSE(different.AreAllCornersSame(.02));
317 }
318 }

References impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TSize< T >::height, impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [368/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiDefaultConstructor |
| ) |  |

Definition at line 34 of file round_rect_unittests.cc.

34 {
35 RoundingRadii radii = RoundingRadii();
36
37 EXPECT_TRUE(radii.AreAllCornersEmpty());
38 EXPECT_TRUE(radii.AreAllCornersSame());
39 EXPECT_TRUE(radii.IsFinite());
40 EXPECT_EQ(radii.top_left, Size());
41 EXPECT_EQ(radii.top_right, Size());
42 EXPECT_EQ(radii.bottom_left, Size());
43 EXPECT_EQ(radii.bottom_right, Size());
44 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [369/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiEmptyDeclaration |
| ) |  |

Definition at line 14 of file round_rect_unittests.cc.

14 {
15 RoundingRadii radii;
16
17 EXPECT_TRUE(radii.AreAllCornersEmpty());
18 EXPECT_TRUE(radii.AreAllCornersSame());
19 EXPECT_TRUE(radii.IsFinite());
20 EXPECT_EQ(radii.top_left, Size());
21 EXPECT_EQ(radii.top_right, Size());
22 EXPECT_EQ(radii.bottom_left, Size());
23 EXPECT_EQ(radii.bottom_right, Size());
24 EXPECT_EQ(radii.top_left.width, 0.0f);
25 EXPECT_EQ(radii.top_left.height, 0.0f);
26 EXPECT_EQ(radii.top_right.width, 0.0f);
27 EXPECT_EQ(radii.top_right.height, 0.0f);
28 EXPECT_EQ(radii.bottom_left.width, 0.0f);
29 EXPECT_EQ(radii.bottom_left.height, 0.0f);
30 EXPECT_EQ(radii.bottom_right.width, 0.0f);
31 EXPECT_EQ(radii.bottom_right.height, 0.0f);
32 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TSize< T >::height, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [370/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiEmptyScalarConstructor |
| ) |  |

Definition at line 58 of file round_rect_unittests.cc.

58 {
59 RoundingRadii radii = RoundingRadii::MakeRadius(-5.0f);
60
61 EXPECT_TRUE(radii.AreAllCornersEmpty());
62 EXPECT_TRUE(radii.AreAllCornersSame());
63 EXPECT_TRUE(radii.IsFinite());
64 EXPECT_EQ(radii.top_left, Size(-5.0f, -5.0f));
65 EXPECT_EQ(radii.top_right, Size(-5.0f, -5.0f));
66 EXPECT_EQ(radii.bottom_left, Size(-5.0f, -5.0f));
67 EXPECT_EQ(radii.bottom_right, Size(-5.0f, -5.0f));
68 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadius(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [371/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiEmptySizeConstructor |
| ) |  |

Definition at line 82 of file round_rect_unittests.cc.

82 {
83 {
84 RoundingRadii radii = RoundingRadii::MakeRadii(Size(-5.0f, 6.0f));
85
86 EXPECT_TRUE(radii.AreAllCornersEmpty());
87 EXPECT_TRUE(radii.AreAllCornersSame());
88 EXPECT_TRUE(radii.IsFinite());
89 EXPECT_EQ(radii.top_left, Size(-5.0f, 6.0f));
90 EXPECT_EQ(radii.top_right, Size(-5.0f, 6.0f));
91 EXPECT_EQ(radii.bottom_left, Size(-5.0f, 6.0f));
92 EXPECT_EQ(radii.bottom_right, Size(-5.0f, 6.0f));
93 }
94
95 {
96 RoundingRadii radii = RoundingRadii::MakeRadii(Size(5.0f, -6.0f));
97
98 EXPECT_TRUE(radii.AreAllCornersEmpty());
99 EXPECT_TRUE(radii.AreAllCornersSame());
100 EXPECT_TRUE(radii.IsFinite());
101 EXPECT_EQ(radii.top_left, Size(5.0f, -6.0f));
102 EXPECT_EQ(radii.top_right, Size(5.0f, -6.0f));
103 EXPECT_EQ(radii.bottom_left, Size(5.0f, -6.0f));
104 EXPECT_EQ(radii.bottom_right, Size(5.0f, -6.0f));
105 }
106 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadii(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [372/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiEquals |
| ) |  |

Definition at line 201 of file round_rect_unittests.cc.

201 {
202 RoundingRadii radii = {
203 .top_left = Size(5.0f, 5.5f),
204 .top_right = Size(6.0f, 6.5f),
205 .bottom_left = Size(7.0f, 7.5f),
206 .bottom_right = Size(8.0f, 8.5f),
207 };
208 RoundingRadii other = {
209 .top_left = Size(5.0f, 5.5f),
210 .top_right = Size(6.0f, 6.5f),
211 .bottom_left = Size(7.0f, 7.5f),
212 .bottom_right = Size(8.0f, 8.5f),
213 };
214
215 EXPECT_EQ(radii, other);
216 }

References impeller::RoundingRadii::top_left.

## ◆ TEST() [373/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiMultiply |
| ) |  |

Definition at line 183 of file round_rect_unittests.cc.

183 {
184 RoundingRadii radii = {
185 .top_left = Size(5.0f, 5.5f),
186 .top_right = Size(6.0f, 6.5f),
187 .bottom_left = Size(7.0f, 7.5f),
188 .bottom_right = Size(8.0f, 8.5f),
189 };
190 RoundingRadii doubled = radii * 2.0f;
191
192 EXPECT_FALSE(doubled.AreAllCornersEmpty());
193 EXPECT_FALSE(doubled.AreAllCornersSame());
194 EXPECT_TRUE(doubled.IsFinite());
195 EXPECT_EQ(doubled.top_left, Size(10.0f, 11.0f));
196 EXPECT_EQ(doubled.top_right, Size(12.0f, 13.0f));
197 EXPECT_EQ(doubled.bottom_left, Size(14.0f, 15.0f));
198 EXPECT_EQ(doubled.bottom_right, Size(16.0f, 17.0f));
199 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [374/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiNamedSizesConstructor |
| ) |  |

Definition at line 108 of file round_rect_unittests.cc.

108 {
109 RoundingRadii radii = {
110 .top_left = Size(5.0f, 5.5f),
111 .top_right = Size(6.0f, 6.5f),
112 .bottom_left = Size(7.0f, 7.5f),
113 .bottom_right = Size(8.0f, 8.5f),
114 };
115
116 EXPECT_FALSE(radii.AreAllCornersEmpty());
117 EXPECT_FALSE(radii.AreAllCornersSame());
118 EXPECT_TRUE(radii.IsFinite());
119 EXPECT_EQ(radii.top_left, Size(5.0f, 5.5f));
120 EXPECT_EQ(radii.top_right, Size(6.0f, 6.5f));
121 EXPECT_EQ(radii.bottom_left, Size(7.0f, 7.5f));
122 EXPECT_EQ(radii.bottom_right, Size(8.0f, 8.5f));
123 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [375/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiNotEquals |
| ) |  |

Definition at line 218 of file round_rect_unittests.cc.

218 {
219 const RoundingRadii radii = {
220 .top_left = Size(5.0f, 5.5f),
221 .top_right = Size(6.0f, 6.5f),
222 .bottom_left = Size(7.0f, 7.5f),
223 .bottom_right = Size(8.0f, 8.5f),
224 };
225
226 {
227 RoundingRadii different = radii;
228 different.top_left.width = 100.0f;
229 EXPECT_NE(different, radii);
230 }
231 {
232 RoundingRadii different = radii;
233 different.top_left.height = 100.0f;
234 EXPECT_NE(different, radii);
235 }
236 {
237 RoundingRadii different = radii;
238 different.top_right.width = 100.0f;
239 EXPECT_NE(different, radii);
240 }
241 {
242 RoundingRadii different = radii;
243 different.top_right.height = 100.0f;
244 EXPECT_NE(different, radii);
245 }
246 {
247 RoundingRadii different = radii;
248 different.bottom_left.width = 100.0f;
249 EXPECT_NE(different, radii);
250 }
251 {
252 RoundingRadii different = radii;
253 different.bottom_left.height = 100.0f;
254 EXPECT_NE(different, radii);
255 }
256 {
257 RoundingRadii different = radii;
258 different.bottom_right.width = 100.0f;
259 EXPECT_NE(different, radii);
260 }
261 {
262 RoundingRadii different = radii;
263 different.bottom_right.height = 100.0f;
264 EXPECT_NE(different, radii);
265 }
266 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TSize< T >::height, impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [376/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiPartialNamedSizesConstructor |
| ) |  |

Definition at line 125 of file round_rect_unittests.cc.

125 {
126 {
127 RoundingRadii radii = {
128 .top_left = Size(5.0f, 5.5f),
129 };
130
131 EXPECT_FALSE(radii.AreAllCornersEmpty());
132 EXPECT_FALSE(radii.AreAllCornersSame());
133 EXPECT_TRUE(radii.IsFinite());
134 EXPECT_EQ(radii.top_left, Size(5.0f, 5.5f));
135 EXPECT_EQ(radii.top_right, Size());
136 EXPECT_EQ(radii.bottom_left, Size());
137 EXPECT_EQ(radii.bottom_right, Size());
138 }
139
140 {
141 RoundingRadii radii = {
142 .top_right = Size(6.0f, 6.5f),
143 };
144
145 EXPECT_FALSE(radii.AreAllCornersEmpty());
146 EXPECT_FALSE(radii.AreAllCornersSame());
147 EXPECT_TRUE(radii.IsFinite());
148 EXPECT_EQ(radii.top_left, Size());
149 EXPECT_EQ(radii.top_right, Size(6.0f, 6.5f));
150 EXPECT_EQ(radii.bottom_left, Size());
151 EXPECT_EQ(radii.bottom_right, Size());
152 }
153
154 {
155 RoundingRadii radii = {
156 .bottom_left = Size(7.0f, 7.5f),
157 };
158
159 EXPECT_FALSE(radii.AreAllCornersEmpty());
160 EXPECT_FALSE(radii.AreAllCornersSame());
161 EXPECT_TRUE(radii.IsFinite());
162 EXPECT_EQ(radii.top_left, Size());
163 EXPECT_EQ(radii.top_right, Size());
164 EXPECT_EQ(radii.bottom_left, Size(7.0f, 7.5f));
165 EXPECT_EQ(radii.bottom_right, Size());
166 }
167
168 {
169 RoundingRadii radii = {
170 .bottom_right = Size(8.0f, 8.5f),
171 };
172
173 EXPECT_FALSE(radii.AreAllCornersEmpty());
174 EXPECT_FALSE(radii.AreAllCornersSame());
175 EXPECT_TRUE(radii.IsFinite());
176 EXPECT_EQ(radii.top_left, Size());
177 EXPECT_EQ(radii.top_right, Size());
178 EXPECT_EQ(radii.bottom_left, Size());
179 EXPECT_EQ(radii.bottom_right, Size(8.0f, 8.5f));
180 }
181 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [377/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiScalarConstructor |
| ) |  |

Definition at line 46 of file round_rect_unittests.cc.

46 {
47 RoundingRadii radii = RoundingRadii::MakeRadius(5.0f);
48
49 EXPECT_FALSE(radii.AreAllCornersEmpty());
50 EXPECT_TRUE(radii.AreAllCornersSame());
51 EXPECT_TRUE(radii.IsFinite());
52 EXPECT_EQ(radii.top_left, Size(5.0f, 5.0f));
53 EXPECT_EQ(radii.top_right, Size(5.0f, 5.0f));
54 EXPECT_EQ(radii.bottom_left, Size(5.0f, 5.0f));
55 EXPECT_EQ(radii.bottom_right, Size(5.0f, 5.0f));
56 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadius(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [378/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RoundingRadiiSizeConstructor |
| ) |  |

Definition at line 70 of file round_rect_unittests.cc.

70 {
71 RoundingRadii radii = RoundingRadii::MakeRadii(Size(5.0f, 6.0f));
72
73 EXPECT_FALSE(radii.AreAllCornersEmpty());
74 EXPECT_TRUE(radii.AreAllCornersSame());
75 EXPECT_TRUE(radii.IsFinite());
76 EXPECT_EQ(radii.top_left, Size(5.0f, 6.0f));
77 EXPECT_EQ(radii.top_right, Size(5.0f, 6.0f));
78 EXPECT_EQ(radii.bottom_left, Size(5.0f, 6.0f));
79 EXPECT_EQ(radii.bottom_right, Size(5.0f, 6.0f));
80 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadii(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [379/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | Shift |
| ) |  |

Definition at line 578 of file round_rect_unittests.cc.

578 {
579 RoundRect round_rect =
580 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
581 {
582 .top_left = Size(1.0f, 2.0f),
583 .top_right = Size(3.0f, 4.0f),
584 .bottom_left = Size(5.0f, 6.0f),
585 .bottom_right = Size(7.0f, 8.0f),
586 });
587 RoundRect shifted = round_rect.Shift(5.0, 6.0);
588
589 EXPECT_FALSE(shifted.IsEmpty());
590 EXPECT_FALSE(shifted.IsRect());
591 EXPECT_FALSE(shifted.IsOval());
592 EXPECT_TRUE(shifted.IsFinite());
593 EXPECT_FALSE(shifted.GetBounds().IsEmpty());
594 EXPECT_EQ(shifted.GetBounds(), Rect::MakeLTRB(15.0f, 16.0f, 45.0f, 46.0f));
595 EXPECT_EQ(shifted.GetRadii().top_left, Size(1.0f, 2.0f));
596 EXPECT_EQ(shifted.GetRadii().top_right, Size(3.0f, 4.0f));
597 EXPECT_EQ(shifted.GetRadii().bottom_left, Size(5.0f, 6.0f));
598 EXPECT_EQ(shifted.GetRadii().bottom_right, Size(7.0f, 8.0f));
599
600 EXPECT_EQ(shifted,
601 RoundRect::MakeRectRadii(Rect::MakeXYWH(15.0f, 16.0f, 30.0f, 30.0f),
602 {
603 .top_left = Size(1.0f, 2.0f),
604 .top_right = Size(3.0f, 4.0f),
605 .bottom_left = Size(5.0f, 6.0f),
606 .bottom_right = Size(7.0f, 8.0f),
607 }));
608 }

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

## ◆ TEST() [380/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | TinyCornerRoundRectContains |
| ) |  |

Definition at line 873 of file round_rect_unittests.cc.

873 {
874 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
875 // RRect of bounds with even the tiniest corners does not contain corners
876 auto tiny_corners = RoundRect::MakeRectXY(bounds, 0.01f, 0.01f);
877
878 EXPECT_FALSE(tiny_corners.Contains({-50, -50}));
879 EXPECT_FALSE(tiny_corners.Contains({-50, 50}));
880 EXPECT_FALSE(tiny_corners.Contains({50, -50}));
881 EXPECT_FALSE(tiny_corners.Contains({50, 50}));
882 }

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

## ◆ TEST() [381/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | UniformCircularRoundRectContains |
| ) |  |

Definition at line 884 of file round_rect_unittests.cc.

884 {
885 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
886 auto expanded_2_r_2 = RoundRect::MakeRectXY(bounds.Expand(2.0), 2.0f, 2.0f);
887
888 // Expanded by 2.0 and then with a corner of 2.0 obviously still
889 // contains the corners
890 EXPECT_TRUE(expanded_2_r_2.Contains({-50, -50}));
891 EXPECT_TRUE(expanded_2_r_2.Contains({-50, 50}));
892 EXPECT_TRUE(expanded_2_r_2.Contains({50, -50}));
893 EXPECT_TRUE(expanded_2_r_2.Contains({50, 50}));
894
895 // Now we try to box in the corner containment to exactly where the
896 // rounded corner of the expanded round rect with radii of 2.0 lies.
897 // The 45-degree diagonal point of a circle of radius 2.0 lies at:
898 //
899 // (2 * sqrt(2) / 2, 2 * sqrt(2) / 2)
900 // (sqrt(2), sqrt(2))
901 //
902 // So we test +/- (50 + sqrt(2) +/- epsilon)
903 const auto coord_out = 50 + kSqrt2 + kEhCloseEnough;
904 const auto coord_in = 50 + kSqrt2 - kEhCloseEnough;
905 // Upper left corner
906 EXPECT_TRUE(expanded_2_r_2.Contains({-coord_in, -coord_in}));
907 EXPECT_FALSE(expanded_2_r_2.Contains({-coord_out, -coord_out}));
908 // Upper right corner
909 EXPECT_TRUE(expanded_2_r_2.Contains({coord_in, -coord_in}));
910 EXPECT_FALSE(expanded_2_r_2.Contains({coord_out, -coord_out}));
911 // Lower left corner
912 EXPECT_TRUE(expanded_2_r_2.Contains({-coord_in, coord_in}));
913 EXPECT_FALSE(expanded_2_r_2.Contains({-coord_out, coord_out}));
914 // Lower right corner
915 EXPECT_TRUE(expanded_2_r_2.Contains({coord_in, coord_in}));
916 EXPECT_FALSE(expanded_2_r_2.Contains({coord_out, coord_out}));
917 }

References impeller::TRect< T >::Expand(), impeller::kEhCloseEnough, impeller::kSqrt2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectXY().

## ◆ TEST() [382/465]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | UniformEllipticalRoundRectContains |
| ) |  |

Definition at line 919 of file round_rect_unittests.cc.

919 {
920 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
921 auto expanded_2_r_2 = RoundRect::MakeRectXY(bounds.Expand(2.0), 2.0f, 3.0f);
922
923 // Expanded by 2.0 and then with a corner of 2x3 should still
924 // contain the corners
925 EXPECT_TRUE(expanded_2_r_2.Contains({-50, -50}));
926 EXPECT_TRUE(expanded_2_r_2.Contains({-50, 50}));
927 EXPECT_TRUE(expanded_2_r_2.Contains({50, -50}));
928 EXPECT_TRUE(expanded_2_r_2.Contains({50, 50}));
929
930 // Now we try to box in the corner containment to exactly where the
931 // rounded corner of the expanded round rect with radii of 2x3 lies.
932 // The "45-degree diagonal point" of an ellipse of radii 2x3 lies at:
933 //
934 // (2 * sqrt(2) / 2, 3 * sqrt(2) / 2)
935 // (sqrt(2), 3 * sqrt(2) / 2)
936 //
937 // And the center(s) of these corners are at:
938 // (+/-(50 + 2 - 2), +/-(50 + 2 - 3))
939 // = (+/-50, +/-49)
940 const auto x_coord_out = 50 + kSqrt2 + kEhCloseEnough;
941 const auto x_coord_in = 50 + kSqrt2 - kEhCloseEnough;
942 const auto y_coord_out = 49 + 3 * kSqrt2 / 2 + kEhCloseEnough;
943 const auto y_coord_in = 49 + 3 * kSqrt2 / 2 - kEhCloseEnough;
944 // Upper left corner
945 EXPECT_TRUE(expanded_2_r_2.Contains({-x_coord_in, -y_coord_in}));
946 EXPECT_FALSE(expanded_2_r_2.Contains({-x_coord_out, -y_coord_out}));
947 // Upper right corner
948 EXPECT_TRUE(expanded_2_r_2.Contains({x_coord_in, -y_coord_in}));
949 EXPECT_FALSE(expanded_2_r_2.Contains({x_coord_out, -y_coord_out}));
950 // Lower left corner
951 EXPECT_TRUE(expanded_2_r_2.Contains({-x_coord_in, y_coord_in}));
952 EXPECT_FALSE(expanded_2_r_2.Contains({-x_coord_out, y_coord_out}));
953 // Lower right corner
954 EXPECT_TRUE(expanded_2_r_2.Contains({x_coord_in, y_coord_in}));
955 EXPECT_FALSE(expanded_2_r_2.Contains({x_coord_out, y_coord_out}));
956 }

References impeller::TRect< T >::Expand(), impeller::kEhCloseEnough, impeller::kSqrt2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectXY().

## ◆ TEST() [383/465]

impeller::testing::TEST | ( | RSTransformTest | ,
|  | CompareToMatrix |
| ) |  |

Definition at line 32 of file rstransform_unittests.cc.

32 {
33 for (int tx = 0; tx <= 100; tx += 10) {
34 for (int ty = 0; ty <= 100; ty += 10) {
35 Point origin(tx, ty);
36 for (int scale = 1; scale <= 20; scale += 5) {
37 // Overshoot a full circle by 30 degrees
38 for (int degrees = 0; degrees <= 390; degrees += 45) {
39 auto matrix = Matrix::MakeTranslation(origin) *
40 Matrix::MakeRotationZ(Degrees(degrees)) *
41 Matrix::MakeScale(Vector2(scale, scale));
42 auto rst = RSTransform::Make(origin, scale, Degrees(degrees));
43 EXPECT_MATRIX_NEAR(rst.GetMatrix(), matrix);
44 for (int w = 10; w <= 100; w += 10) {
45 for (int h = 10; h <= 100; h += 10) {
46 Quad q = rst.GetQuad(w, h);
47 auto points = Rect::MakeWH(w, h).GetTransformedPoints(matrix);
48 for (int i = 0; i < 4; i++) {
49 EXPECT_NEAR(q[i].x, points[i].x, kEhCloseEnough);
50 EXPECT_NEAR(q[i].y, points[i].y, kEhCloseEnough);
51 }
52 }
53 }
54 }
55 }
56 }
57 }
58 }

References EXPECT_MATRIX_NEAR, impeller::TRect< T >::GetTransformedPoints(), impeller::kEhCloseEnough, impeller::RSTransform::Make(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeWH(), scale, and x.

## ◆ TEST() [384/465]

impeller::testing::TEST | ( | RSTransformTest | ,
|  | Construction |
| ) |  |

Definition at line 14 of file rstransform_unittests.cc.

14 {
15 RSTransform transform = RSTransform::Make({10.0f, 12.0f}, 2.0f, Degrees(90));
16
17 EXPECT_EQ(transform.scaled_cos, 0.0f);
18 EXPECT_EQ(transform.scaled_sin, 2.0f);
19 EXPECT_EQ(transform.translate_x, 10.0f);
20 EXPECT_EQ(transform.translate_y, 12.0f);
21
22 EXPECT_EQ(transform.GetBounds(20.0f, 30.0f),
23 // relative corners are at
24 // 0, 0
25 // 0, 40
26 // -60, 0
27 // -60, 40
28 // then add 10, 12 to all values
29 Rect::MakeLTRB(10 + -2 * 30, 12 + 0, 10 + 0, 12 + 40));
30 }

References impeller::RSTransform::Make(), impeller::TRect< Scalar >::MakeLTRB(), and transform.

## ◆ TEST() [385/465]

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() [386/465]

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() [387/465]

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() [388/465]

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

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() [390/465]

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() [391/465]

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() [392/465]

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() [393/465]

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() [394/465]

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() [395/465]

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() [396/465]

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() [397/465]

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() [398/465]

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() [399/465]

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() [400/465]

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() [401/465]

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() [402/465]

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() [403/465]

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() [404/465]

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() [405/465]

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() [406/465]

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() [407/465]

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() [408/465]

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() [409/465]

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() [410/465]

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() [411/465]

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() [412/465]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DontRoundUpCoverageWhenNotCloseToCoverageLimitHeight |
| ) |  |

Definition at line 311 of file save_layer_utils_unittests.cc.

311 {
312 // X varies, translation is performed on coverage.
313 auto coverage = ComputeSaveLayerCoverage(
314 /*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 50), //
315 /*effect_transform=*/{}, //
316 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
317 /*image_filter=*/nullptr //
318 );
319
320 ASSERT_TRUE(coverage.has_value());
321 // Size that matches coverage limit
322 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 90, 50));
323 }

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

## ◆ TEST() [413/465]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DontRoundUpCoverageWhenNotCloseToCoverageLimitWidth |
| ) |  |

Definition at line 297 of file save_layer_utils_unittests.cc.

297 {
298 // X varies, translation is performed on coverage.
299 auto coverage = ComputeSaveLayerCoverage(
300 /*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 90), //
301 /*effect_transform=*/{}, //
302 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
303 /*image_filter=*/nullptr //
304 );
305
306 ASSERT_TRUE(coverage.has_value());
307 // Size that matches coverage limit
308 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 90));
309 }

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

## ◆ TEST() [414/465]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DontRoundUpCoverageWhenNotCloseToCoverageLimitWidthHeight |
| ) |  |

Definition at line 325 of file save_layer_utils_unittests.cc.

326 {
327 // X varies, translation is performed on coverage.
328 auto coverage = ComputeSaveLayerCoverage(
329 /*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 50), //
330 /*effect_transform=*/{}, //
331 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
332 /*image_filter=*/nullptr //
333 );
334
335 ASSERT_TRUE(coverage.has_value());
336 // Size that matches coverage limit
337 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
338 }

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

## ◆ TEST() [415/465]

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() [416/465]

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() [417/465]

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() [418/465]

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() [419/465]

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() [420/465]

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() [421/465]

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() [422/465]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | RoundUpCoverageWhenCloseToCoverageLimit |
| ) |  |

Definition at line 283 of file save_layer_utils_unittests.cc.

283 {
284 // X varies, translation is performed on coverage.
285 auto coverage = ComputeSaveLayerCoverage(
286 /*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 90), //
287 /*effect_transform=*/{}, //
288 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
289 /*image_filter=*/nullptr //
290 );
291
292 ASSERT_TRUE(coverage.has_value());
293 // Size that matches coverage limit
294 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
295 }

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

## ◆ TEST() [423/465]

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() [424/465]

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() [425/465]

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() [426/465]

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() [427/465]

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() [428/465]

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() [429/465]

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() [430/465]

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() [431/465]

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(flutter::DlPoint(0, 0), //
241 flutter::DlPoint(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->asLinearGradient(), 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() [432/465]

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(flutter::DlPoint(0, 0), //
162 flutter::DlPoint(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->asLinearGradient(), 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() [433/465]

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(flutter::DlPoint(0, 0), //
188 flutter::DlPoint(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->asLinearGradient(), 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() [434/465]

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(flutter::DlPoint(0, 0), //
138 flutter::DlPoint(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->asLinearGradient(), 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() [435/465]

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(flutter::DlPoint(0, 0), //
215 flutter::DlPoint(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->asLinearGradient(), 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() [436/465]

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() [437/465]

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(), and x.

## ◆ TEST() [438/465]

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(), and x.

## ◆ TEST() [439/465]

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 impeller::ScalarNearlyEqual(), and impeller::skia_conversions::ToColor().

## ◆ TEST() [440/465]

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() [441/465]

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() [442/465]

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() [443/465]

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() [444/465]

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() [445/465]

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() [446/465]

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() [447/465]

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() [448/465]

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() [449/465]

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() [450/465]

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() [451/465]

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() [452/465]

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() [453/465]

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() [454/465]

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() [455/465]

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() [456/465]

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() [457/465]

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() [458/465]

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() [459/465]

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() [460/465]

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() [461/465]

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() [462/465]

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() [463/465]

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() [464/465]

impeller::testing::TEST | ( | TypographerTest | ,
|  | RectanglePackerFillsRows |
| ) |  |

Definition at line 404 of file typographer_unittests.cc.

404 {
405 auto skyline = RectanglePacker::Factory(257, 256);
406
407 // Fill up the first row.
408 IPoint16 loc;
409 for (auto i = 0u; i < 16; i++) {
410 skyline->AddRect(16, 16, &loc);
411 }
412 // Last rectangle still in first row.
413 EXPECT_EQ(loc.x(), 256 - 16);
414 EXPECT_EQ(loc.y(), 0);
415
416 // Fill up second row.
417 for (auto i = 0u; i < 16; i++) {
418 skyline->AddRect(16, 16, &loc);
419 }
420
421 EXPECT_EQ(loc.x(), 256 - 16);
422 EXPECT_EQ(loc.y(), 16);
423 }

References impeller::RectanglePacker::Factory(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ TEST() [465/465]

impeller::testing::TEST | ( | UniqueHandleGLES | ,
|  | MakeUntracked |
| ) |  |

Definition at line 26 of file unique_handle_gles_unittests.cc.

26 {
27 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
28
29 EXPECT_CALL(*mock_gles_impl, GenTextures(1, _)).Times(1);
30
31 std::shared_ptr<MockGLES> mock_gled =
32 MockGLES::Init(std::move(mock_gles_impl));
33 ProcTableGLES::Resolver resolver = kMockResolverGLES;
34 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
35 auto worker = std::make_shared<TestWorker>();
36 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
37 reactor->AddWorker(worker);
38
39 UniqueHandleGLES handle =
40 UniqueHandleGLES::MakeUntracked(reactor, HandleType::kTexture);
41 EXPECT_FALSE(handle.Get().IsDead());
42 }

References impeller::UniqueHandleGLES::Get(), impeller::HandleGLES::IsDead(), impeller::kTexture, and impeller::UniqueHandleGLES::MakeUntracked().

## ◆ 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::DlColorSource::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/494]

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

Definition at line 909 of file aiks_dl_blend_unittests.cc.

909 {
910 DisplayListBuilder builder;
911
912 builder.DrawPaint(DlPaint(DlColor::kWhite()));
913
914 DlPaint save_paint;
915 save_paint.setOpacity(0.3);
916 save_paint.setColorFilter(DlColorFilter::MakeBlend(DlColor::kTransparent(),
917 DlBlendMode::kSaturation));
918 builder.SaveLayer(nullptr, &save_paint);
919 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300),
920 DlPaint(DlColor::kMaroon()));
921 builder.DrawRect(SkRect::MakeXYWH(200, 200, 300, 300),
922 DlPaint(DlColor::kBlue()));
923 builder.Restore();
924
925 // Should be solid red as the destructive color filter floods the clip.
926 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
927 }

## ◆ TEST_P() [2/494]

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 }

References x.

## ◆ TEST_P() [3/494]

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

Definition at line 174 of file canvas_unittests.cc.

174 {
175 ContentContext context(GetContext(), nullptr);
176 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
177 GTEST_SKIP() << "Test requires device with framebuffer fetch";
178 }
179 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
180 /*requires_readback=*/true);
181 // 3 backdrop filters all with same id.
182 std::unordered_map<int64_t, BackdropData> data;
183 data[1] = BackdropData{.backdrop_count = 3};
184 canvas->SetBackdropData(data, 3);
185
186 auto blur =
187 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
188
189 EXPECT_TRUE(canvas->RequiresReadback());
190 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
191 {.color = Color::Azure()});
192 canvas->SaveLayer({}, std::nullopt, blur.get(),
193 ContentBoundsPromise::kContainsContents,
194 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
195 /*backdrop_id=*/1);
196 canvas->Restore();
197 EXPECT_FALSE(canvas->RequiresReadback());
198
199 canvas->SaveLayer({}, std::nullopt, blur.get(),
200 ContentBoundsPromise::kContainsContents,
201 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
202 /*backdrop_id=*/1);
203 canvas->Restore();
204 EXPECT_FALSE(canvas->RequiresReadback());
205
206 canvas->SaveLayer({}, std::nullopt, blur.get(),
207 ContentBoundsPromise::kContainsContents,
208 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
209 /*backdrop_id=*/1);
210 canvas->Restore();
211 EXPECT_FALSE(canvas->RequiresReadback());
212 }

References impeller::Color::Azure(), impeller::BackdropData::backdrop_count, CreateTestCanvas(), data, impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [4/494]

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

Definition at line 214 of file canvas_unittests.cc.

214 {
215 ContentContext context(GetContext(), nullptr);
216 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
217 GTEST_SKIP() << "Test requires device with framebuffer fetch";
218 }
219 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
220 /*requires_readback=*/true);
221 // 3 backdrop filters, 2 with same id.
222 std::unordered_map<int64_t, BackdropData> data;
223 data[1] = BackdropData{.backdrop_count = 2};
224 canvas->SetBackdropData(data, 3);
225
226 auto blur =
227 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
228
229 EXPECT_TRUE(canvas->RequiresReadback());
230 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
231 {.color = Color::Azure()});
232 canvas->SaveLayer({}, std::nullopt, blur.get(),
233 ContentBoundsPromise::kContainsContents, 1, false);
234 canvas->Restore();
235 EXPECT_TRUE(canvas->RequiresReadback());
236
237 canvas->SaveLayer({}, std::nullopt, blur.get(),
238 ContentBoundsPromise::kContainsContents, 1, false, 1);
239 canvas->Restore();
240 EXPECT_FALSE(canvas->RequiresReadback());
241
242 canvas->SaveLayer({}, std::nullopt, blur.get(),
243 ContentBoundsPromise::kContainsContents, 1, false, 1);
244 canvas->Restore();
245 EXPECT_FALSE(canvas->RequiresReadback());
246 }

References impeller::Color::Azure(), impeller::BackdropData::backdrop_count, CreateTestCanvas(), data, impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [5/494]

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

Definition at line 139 of file canvas_unittests.cc.

139 {
140 ContentContext context(GetContext(), nullptr);
141 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
142 GTEST_SKIP() << "Test requires device with framebuffer fetch";
143 }
144 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
145 /*requires_readback=*/true);
146 // 3 backdrop filters
147 canvas->SetBackdropData({}, 3);
148
149 auto blur =
150 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
151 flutter::DlRect rect = flutter::DlRect::MakeLTRB(0, 0, 50, 50);
152
153 EXPECT_TRUE(canvas->RequiresReadback());
154 canvas->DrawRect(rect, {.color = Color::Azure()});
155 canvas->SaveLayer({}, rect, blur.get(),
156 ContentBoundsPromise::kContainsContents,
157 /*total_content_depth=*/1);
158 canvas->Restore();
159 EXPECT_TRUE(canvas->RequiresReadback());
160
161 canvas->SaveLayer({}, rect, blur.get(),
162 ContentBoundsPromise::kContainsContents,
163 /*total_content_depth=*/1);
164 canvas->Restore();
165 EXPECT_TRUE(canvas->RequiresReadback());
166
167 canvas->SaveLayer({}, rect, blur.get(),
168 ContentBoundsPromise::kContainsContents,
169 /*total_content_depth=*/1);
170 canvas->Restore();
171 EXPECT_FALSE(canvas->RequiresReadback());
172 }

References impeller::Color::Azure(), CreateTestCanvas(), impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [6/494]

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

Definition at line 251 of file canvas_unittests.cc.

251 {
252 ContentContext context(GetContext(), nullptr);
253 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
254 GTEST_SKIP() << "Test requires device with framebuffer fetch";
255 }
256 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
257 /*requires_readback=*/true);
258
259 canvas->SetBackdropData({}, 2);
260
261 auto blur =
262 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
263
264 EXPECT_TRUE(canvas->RequiresReadback());
265 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
266 {.color = Color::Azure()});
267 canvas->SaveLayer({}, std::nullopt, blur.get(),
268 ContentBoundsPromise::kContainsContents,
269 /*total_content_depth=*/3);
270
271 // This filter is nested in the first saveLayer. We cannot restore to onscreen
272 // here.
273 canvas->SaveLayer({}, std::nullopt, blur.get(),
274 ContentBoundsPromise::kContainsContents,
275 /*total_content_depth=*/1);
276 canvas->Restore();
277 EXPECT_TRUE(canvas->RequiresReadback());
278
279 canvas->Restore();
280 EXPECT_TRUE(canvas->RequiresReadback());
281 }

References impeller::Color::Azure(), CreateTestCanvas(), impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [7/494]

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

Definition at line 1594 of file aiks_dl_basic_unittests.cc.

1594 {
1595 DisplayListBuilder builder;
1596
1597 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1598 builder.Save();
1599 {
1600 builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
1601
1602 builder.Save();
1603 {
1604 builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
1605 builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
1606 builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
1607 builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
1608 builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
1609 }
1610 builder.Restore();
1611
1612 auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
1613 builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
1614 }
1615 builder.Restore();
1616 builder.DrawCircle(SkPoint{100, 100}, 100,
1617 DlPaint().setColor(DlColor::kAqua()));
1618
1619 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1620 }

## ◆ TEST_P() [8/494]

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

Definition at line 910 of file aiks_dl_unittests.cc.

910 {
911 DisplayListBuilder builder;
912
913 DlPaint paint;
914 // Add a difference clip that cuts out the bottom right corner
915 builder.ClipRect(SkRect::MakeLTRB(50, 50, 100, 100),
916 DlCanvas::ClipOp::kDifference);
917
918 // Draw a red rectangle that's going to be completely covered by green later.
919 paint.setColor(DlColor::kRed());
920 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
921
922 // Add a clip restricting the backdrop filter to the top right corner.
923 auto count = builder.GetSaveCount();
924 builder.Save();
925 {
926 builder.ClipRect(SkRect::MakeLTRB(0, 0, 100, 100));
927 {
928 // Create a save layer with a backdrop blur filter.
929 auto backdrop_filter =
930 DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal);
931 builder.SaveLayer(nullptr, nullptr, backdrop_filter.get());
932 }
933 }
934 builder.RestoreToCount(count);
935
936 // Finally, overwrite all the previous stuff with green.
937 paint.setColor(DlColor::kGreen());
938 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
939
940 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
941 }

## ◆ TEST_P() [9/494]

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

Definition at line 433 of file aiks_dl_blend_unittests.cc.

433 {
434 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
435 PixelFormat::kB10G10R10A10XR);
436 auto texture = CreateTextureForFixture("airplane.jpg",
437 /*enable_mipmapping=*/true);
438
439 DisplayListBuilder builder;
440 builder.Scale(GetContentScale().x, GetContentScale().y);
441
442 DlPaint paint;
443 paint.setColor(DlColor::RGBA(0.1, 0.2, 0.1, 1.0));
444 builder.DrawPaint(paint);
445
446 DlPaint save_paint;
447 save_paint.setColorFilter(
448 DlColorFilter::MakeBlend(DlColor::RGBA(1, 0, 0, 1), DlBlendMode::kPlus));
449 builder.SaveLayer(nullptr, &save_paint);
450
451 paint.setColor(DlColor::kRed());
452 builder.DrawRect(SkRect::MakeXYWH(100, 100, 400, 400), paint);
453
454 paint.setColor(DlColor::kWhite());
455
456 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
457 builder.DrawImageRect(
458 DlImageImpeller::Make(texture),
459 SkRect::MakeSize(
460 SkSize::Make(texture->GetSize().width, texture->GetSize().height)),
461 SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(),
462 rect.GetBottom()),
463 DlImageSampling::kMipmapLinear, &paint);
464 builder.Restore();
465
466 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
467 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), and x.

## ◆ TEST_P() [10/494]

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

Definition at line 400 of file aiks_dl_blend_unittests.cc.

400 {
401 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
402 PixelFormat::kB10G10R10A10XR);
403 auto texture = CreateTextureForFixture("airplane.jpg",
404 /*enable_mipmapping=*/true);
405
406 DisplayListBuilder builder;
407 DlPaint paint;
408 builder.Scale(GetContentScale().x, GetContentScale().y);
409
410 paint.setColor(DlColor::RGBA(0.9, 1, 0.9, 1.0));
411 builder.DrawPaint(paint);
412 builder.SaveLayer(nullptr);
413
414 paint.setBlendMode(DlBlendMode::kPlus);
415 paint.setColor(DlColor::kRed());
416
417 builder.DrawRect(SkRect::MakeXYWH(100, 100, 400, 400), paint);
418 paint.setColor(DlColor::kWhite());
419
420 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
421 builder.DrawImageRect(
422 DlImageImpeller::Make(texture),
423 SkRect::MakeSize(
424 SkSize::Make(texture->GetSize().width, texture->GetSize().height)),
425 SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(),
426 rect.GetBottom()),
427 DlImageSampling::kMipmapLinear, &paint);
428 builder.Restore();
429 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
430 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), and x.

## ◆ TEST_P() [11/494]

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

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

Definition at line 439 of file aiks_dl_blur_unittests.cc.

439 {
440 Scalar sigma = 47.6;
441 auto callback = [&]() -> sk_sp<DisplayList> {
442 if (AiksTest::ImGuiBegin("Controls", nullptr,
443 ImGuiWindowFlags_AlwaysAutoResize)) {
444 ImGui::SliderFloat("Sigma", &sigma, 0, 50);
445 ImGui::End();
446 }
447 DisplayListBuilder builder;
448 builder.Scale(GetContentScale().x, GetContentScale().y);
449 builder.DrawPaint({});
450
451 DlPaint paint;
452 paint.setColor(DlColor::kGreen());
453 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
454
455 builder.DrawRect(SkRect::MakeXYWH(300, 300, 200, 200), paint);
456 return builder.Build();
457 };
458
459 ASSERT_TRUE(OpenPlaygroundHere(callback));
460 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [13/494]

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

Definition at line 1199 of file aiks_dl_blur_unittests.cc.

1199 {
1200 DisplayListBuilder builder;
1201 builder.Scale(GetContentScale().x, GetContentScale().y);
1202
1203 auto paint_lines = [&builder](Scalar dx, Scalar dy, DlPaint paint) {
1204 auto draw_line = [&builder, &paint](SkPoint a, SkPoint b) {
1205 SkPath line = SkPath::Line(a, b);
1206 builder.DrawPath(line, paint);
1207 };
1208 paint.setStrokeWidth(5);
1209 paint.setDrawStyle(DlDrawStyle::kStroke);
1210 draw_line(SkPoint::Make(dx + 100, dy + 100),
1211 SkPoint::Make(dx + 200, dy + 200));
1212 draw_line(SkPoint::Make(dx + 100, dy + 200),
1213 SkPoint::Make(dx + 200, dy + 100));
1214 draw_line(SkPoint::Make(dx + 150, dy + 100),
1215 SkPoint::Make(dx + 200, dy + 150));
1216 draw_line(SkPoint::Make(dx + 100, dy + 150),
1217 SkPoint::Make(dx + 150, dy + 200));
1218 };
1219
1220 AiksContext renderer(GetContext(), nullptr);
1221 DisplayListBuilder recorder_builder;
1222 for (int x = 0; x < 5; ++x) {
1223 for (int y = 0; y < 5; ++y) {
1224 SkRect rect = SkRect::MakeXYWH(x * 20, y * 20, 20, 20);
1225 DlPaint paint;
1226 paint.setColor(((x + y) & 1) == 0 ? DlColor::kYellow()
1227 : DlColor::kBlue());
1228
1229 recorder_builder.DrawRect(rect, paint);
1230 }
1231 }
1232 auto texture =
1233 DisplayListToTexture(recorder_builder.Build(), {100, 100}, renderer);
1234
1235 auto image_source = DlColorSource::MakeImage(
1236 DlImageImpeller::Make(texture), DlTileMode::kRepeat, DlTileMode::kRepeat);
1237 auto blur_filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kDecal);
1238
1239 DlPaint paint;
1240 paint.setColor(DlColor::kDarkGreen());
1241 builder.DrawRect(SkRect::MakeLTRB(0, 0, 300, 600), paint);
1242
1243 paint.setColorSource(image_source);
1244 builder.DrawRect(SkRect::MakeLTRB(100, 100, 200, 200), paint);
1245
1246 paint.setColorSource(nullptr);
1247 paint.setColor(DlColor::kRed());
1248 builder.DrawRect(SkRect::MakeLTRB(300, 0, 600, 600), paint);
1249
1250 paint.setColorSource(image_source);
1251 paint.setImageFilter(blur_filter);
1252 builder.DrawRect(SkRect::MakeLTRB(400, 100, 500, 200), paint);
1253
1254 paint.setImageFilter(nullptr);
1255 paint_lines(0, 300, paint);
1256
1257 paint.setImageFilter(blur_filter);
1258 paint_lines(300, 300, paint);
1259
1260 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1261 }

References impeller::saturated::b, impeller::DisplayListToTexture(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [14/494]

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

Definition at line 156 of file aiks_dl_vertices_unittests.cc.

156 {
157 constexpr Scalar hexagon_radius = 125;
158 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
159 auto center_to_flat = 1.73 / 2 * hexagon_radius;
160
161 // clang-format off
162 std::vector<DlPoint> vertices = {
163 DlPoint(hex_start.x, hex_start.y),
164 DlPoint(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
165 DlPoint(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
166 DlPoint(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
167 DlPoint(hex_start.x, hex_start.y + 2 * hexagon_radius),
168 DlPoint(hex_start.x, hex_start.y + 2 * hexagon_radius),
169 DlPoint(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
170 DlPoint(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
171 DlPoint(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
172 };
173 // clang-format on
174 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
175 auto dl_vertices = flutter::DlVertices::Make(
176 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
177 nullptr, nullptr);
178 flutter::DisplayListBuilder builder;
179 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
180 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
181 }

## ◆ TEST_P() [15/494]

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() [16/494]

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() [17/494]

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() [18/494]

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

Definition at line 410 of file aiks_dl_basic_unittests.cc.

410 {
411 auto medium_turquoise =
412 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
413
414 DisplayListBuilder builder;
415 builder.Scale(0.2, 0.2);
416 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
417 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
418 }

## ◆ TEST_P() [19/494]

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

Definition at line 420 of file aiks_dl_basic_unittests.cc.

420 {
421 auto medium_turquoise =
422 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
423 auto orange_red =
424 DlColor::RGBA(255.0f / 255.0f, 69.0f / 255.0f, 0.0f / 255.0f, 1.0f);
425
426 DisplayListBuilder builder;
427 builder.Scale(0.2, 0.2);
428 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
429 builder.DrawPaint(DlPaint().setColor(orange_red.modulateOpacity(0.5f)));
430 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
431 }

## ◆ TEST_P() [20/494]

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

Definition at line 684 of file aiks_dl_blend_unittests.cc.

684 {
685 auto modes = GetBlendModeSelection();
686
687 auto callback = [&]() -> sk_sp<DisplayList> {
688 static Color background = Color::MediumTurquoise();
689 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
690 static int current_blend_index = 3;
691
692 if (AiksTest::ImGuiBegin("Controls", nullptr,
693 ImGuiWindowFlags_AlwaysAutoResize)) {
694 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
695 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
696 ImGui::ListBox("Blend mode", &current_blend_index,
697 modes.blend_mode_names.data(),
698 modes.blend_mode_names.size());
699 ImGui::End();
700 }
701
702 DisplayListBuilder builder;
703 builder.Scale(0.2, 0.2);
704 DlPaint paint;
705 paint.setColor(DlColor(background.ToARGB()));
706 builder.DrawPaint(paint);
707
708 paint.setColor(DlColor(foreground.ToARGB()));
709 paint.setBlendMode(static_cast<DlBlendMode>(current_blend_index));
710 builder.DrawPaint(paint);
711 return builder.Build();
712 };
713 ASSERT_TRUE(OpenPlaygroundHere(callback));
714 }

References GetBlendModeSelection(), impeller::AiksPlayground::ImGuiBegin(), impeller::Color::MediumTurquoise(), impeller::Color::ToARGB(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [21/494]

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() [22/494]

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

Definition at line 838 of file aiks_dl_basic_unittests.cc.

838 {
839 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
840 int time = 0;
841 auto callback = [&]() -> sk_sp<DisplayList> {
842 DisplayListBuilder builder;
843
844 builder.Save();
845 {
846 builder.Translate(300, 300);
847
848 // 1. Draw/restore a clip before drawing the image, which will get drawn
849 // to the depth buffer behind the image.
850 builder.Save();
851 {
852 DlPaint paint;
853 paint.setColor(DlColor::kGreen());
854 builder.DrawPaint(paint);
855 builder.ClipRect(SkRect::MakeLTRB(-180, -180, 180, 180),
856 DlCanvas::ClipOp::kDifference);
857
858 paint.setColor(DlColor::kBlack());
859 builder.DrawPaint(paint);
860 }
861 builder.Restore(); // Restore rectangle difference clip.
862
863 builder.Save();
864 {
865 // 2. Draw an oval clip that applies to the image, which will get drawn
866 // in front of the image on the depth buffer.
867 builder.ClipOval(SkRect::MakeLTRB(-200, -200, 200, 200));
868
869 Matrix result =
870 Matrix(1.0, 0.0, 0.0, 0.0, //
871 0.0, 1.0, 0.0, 0.0, //
872 0.0, 0.0, 1.0, 0.003, //
873 0.0, 0.0, 0.0, 1.0) *
874 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
875
876 // 3. Draw the rotating image with a perspective transform.
877 builder.Transform(FromImpellerMatrix(result));
878
879 auto image =
880 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
881 auto position = -SkPoint::Make(image->dimensions().fWidth,
882 image->dimensions().fHeight) *
883 0.5;
884 builder.DrawImage(image, position, {});
885 }
886 builder.Restore(); // Restore oval intersect clip.
887
888 // 4. Draw a semi-translucent blue circle atop all previous draws.
889 DlPaint paint;
890 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
891 builder.DrawCircle(SkPoint{}, 230, paint);
892 }
893 builder.Restore(); // Restore translation.
894
895 return builder.Build();
896 };
897 ASSERT_TRUE(OpenPlaygroundHere(callback));
898 }

References impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRotationY(), and impeller::Matrix::Transform().

## ◆ TEST_P() [23/494]

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

Definition at line 411 of file aiks_dl_unittests.cc.

411 {
412 std::vector<SkPoint> points = {
413 {0, 0}, //
414 {100, 100}, //
415 {100, 0}, //
416 {0, 100}, //
417 {0, 0}, //
418 {48, 48}, //
419 {52, 52}, //
420 };
421 DlPaint paint_round;
422 paint_round.setColor(DlColor::kYellow().withAlpha(128));
423 paint_round.setStrokeCap(DlStrokeCap::kRound);
424 paint_round.setStrokeWidth(20);
425
426 DlPaint paint_square;
427 paint_square.setColor(DlColor::kYellow().withAlpha(128));
428 paint_square.setStrokeCap(DlStrokeCap::kSquare);
429 paint_square.setStrokeWidth(20);
430
431 DlPaint background;
432 background.setColor(DlColor::kBlack());
433
434 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
435 builder.DrawPaint(background);
436 builder.Translate(200, 200);
437
438 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
439 paint_round);
440 builder.Translate(150, 0);
441 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
442 paint_square);
443
444 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
445 }

## ◆ TEST_P() [24/494]

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

Definition at line 447 of file aiks_dl_unittests.cc.

447 {
448 auto texture = DlImageImpeller::Make(
449 CreateTextureForFixture("table_mountain_nx.png",
450 /*enable_mipmapping=*/true));
451
452 std::vector<SkPoint> points = {
453 {0, 0}, //
454 {100, 100}, //
455 {100, 0}, //
456 {0, 100}, //
457 {0, 0}, //
458 {48, 48}, //
459 {52, 52}, //
460 };
461
462 auto image_src =
463 DlColorSource::MakeImage(texture, DlTileMode::kClamp, DlTileMode::kClamp);
464
465 DlPaint paint_round;
466 paint_round.setStrokeCap(DlStrokeCap::kRound);
467 paint_round.setColorSource(image_src);
468 paint_round.setStrokeWidth(200);
469
470 DlPaint paint_square;
471 paint_square.setStrokeCap(DlStrokeCap::kSquare);
472 paint_square.setColorSource(image_src);
473 paint_square.setStrokeWidth(200);
474
475 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
476 builder.Translate(200, 200);
477
478 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
479 paint_round);
480 builder.Translate(150, 0);
481 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
482 paint_square);
483
484 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
485 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [25/494]

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

Definition at line 847 of file aiks_dl_unittests.cc.

847 {
848 std::vector<SkPoint> point = {
849 {0, 0}, //
850 };
851
852 DlPaint paint;
853 paint.setStrokeCap(DlStrokeCap::kRound);
854 paint.setColor(DlColor::kRed());
855 paint.setStrokeWidth(100 * 0.000001);
856
857 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
858 builder.Translate(200, 200);
859 builder.Scale(1000000, 1000000);
860
861 builder.DrawPoints(DlCanvas::PointMode::kPoints, point.size(), point.data(),
862 paint);
863 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
864 }

## ◆ TEST_P() [26/494]

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

Definition at line 826 of file aiks_dl_unittests.cc.

826 {
827 std::vector<SkPoint> point = {
828 {0, 0}, //
829 };
830
831 DlPaint paint;
832 paint.setStrokeCap(DlStrokeCap::kRound);
833 paint.setColor(DlColor::kRed());
834 paint.setStrokeWidth(100 * 1000000);
835
836 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
837 builder.Translate(200, 200);
838 builder.Scale(0.000001, 0.000001);
839
840 builder.DrawPoints(DlCanvas::PointMode::kPoints, point.size(), point.data(),
841 paint);
842
843 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
844 }

## ◆ TEST_P() [27/494]

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

Definition at line 970 of file aiks_dl_unittests.cc.

970 {
971 DisplayListBuilder recorder_builder;
972
973 DisplayListBuilder builder;
974 AiksContext renderer(GetContext(), nullptr);
975
976 DlPaint paint;
977 paint.setColor(DlColor::kTransparent());
978 builder.DrawPaint(paint);
979
980 auto result_image =
981 DisplayListToTexture(builder.Build(), ISize{1000, 1000}, renderer);
982 if (result_image) {
983 recorder_builder.DrawImage(DlImageImpeller::Make(result_image), SkPoint{},
984 {});
985
986 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
987 recorder_builder.DrawRect(SkRect::MakeSize({1000, 1000}), paint);
988 }
989
990 ASSERT_TRUE(OpenPlaygroundHere(recorder_builder.Build()));
991 }

References impeller::DisplayListToTexture(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [28/494]

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

Definition at line 1162 of file aiks_dl_basic_unittests.cc.

1162 {
1163 DisplayListBuilder builder;
1164
1165 DlPaint paint;
1166 paint.setColor(DlColor::kRed());
1167 builder.DrawCircle(SkPoint::Make(250, 250), 125, paint);
1168
1169 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1170 }

## ◆ TEST_P() [29/494]

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

Definition at line 1183 of file aiks_dl_basic_unittests.cc.

1183 {
1184 DisplayListBuilder builder;
1185
1186 DlPaint save;
1187 save.setColor(DlColor::kBlack());
1188
1189 SkRect save_bounds = SkRect::MakeXYWH(0, 0, 50, 50);
1190 builder.SaveLayer(&save_bounds, &save);
1191
1192 DlPaint paint;
1193 paint.setColor(DlColor::kRed());
1194 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1195 paint.setColor(DlColor::kGreen());
1196 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100), paint);
1197 paint.setColor(DlColor::kBlue());
1198 builder.DrawRect(SkRect::MakeXYWH(20, 20, 100, 100), paint);
1199
1200 builder.Restore();
1201
1202 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1203 }

## ◆ TEST_P() [30/494]

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

Definition at line 1084 of file aiks_dl_basic_unittests.cc.

1085 {
1086 DisplayListBuilder builder;
1087
1088 DlPaint red;
1089 red.setColor(DlColor::kRed());
1090
1091 DlPaint green;
1092 green.setColor(DlColor::kGreen());
1093
1094 DlPaint blue;
1095 blue.setColor(DlColor::kBlue());
1096
1097 DlPaint save;
1098 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1099
1100 SkRect huge_bounds = SkRect::MakeXYWH(0, 0, 100000, 100000);
1101 builder.SaveLayer(&huge_bounds, &save);
1102
1103 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), red);
1104 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100), green);
1105 builder.DrawRect(SkRect::MakeXYWH(20, 20, 100, 100), blue);
1106
1107 builder.Restore();
1108
1109 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1110 }

## ◆ TEST_P() [31/494]

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

Definition at line 1172 of file aiks_dl_basic_unittests.cc.

1172 {
1173 DisplayListBuilder builder;
1174
1175 DlPaint red;
1176 red.setColor(DlColor::kRed());
1177 builder.Skew(2, 5);
1178 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), red);
1179
1180 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1181 }

## ◆ TEST_P() [32/494]

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

Definition at line 943 of file aiks_dl_unittests.cc.

943 {
944 DisplayListBuilder recorder_canvas;
945 DlPaint paint;
946 paint.setColor(DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0));
947 recorder_canvas.DrawRect(SkRect::MakeXYWH(100.0, 100.0, 600, 600), paint);
948 paint.setColor(DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0));
949 recorder_canvas.DrawRect(SkRect::MakeXYWH(200.0, 200.0, 600, 600), paint);
950
951 DisplayListBuilder canvas;
952 AiksContext renderer(GetContext(), nullptr);
953 paint.setColor(DlColor::kTransparent());
954 canvas.DrawPaint(paint);
955
956 auto image =
957 DisplayListToTexture(recorder_canvas.Build(), {1000, 1000}, renderer);
958 if (image) {
959 canvas.DrawImage(DlImageImpeller::Make(image), SkPoint{}, {});
960 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
961 canvas.DrawRect(SkRect::MakeSize({1000, 1000}), paint);
962 }
963
964 ASSERT_TRUE(OpenPlaygroundHere(canvas.Build()));
965 }

References impeller::DisplayListToTexture(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [33/494]

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(DlColorFilter::MakeBlend(
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() [34/494]

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(SkPoint{100, 100}, 50, paint);
248
249 paint.setColor(DlColor::kGreenYellow());
250 builder.DrawCircle(SkPoint{300, 200}, 100, paint);
251
252 paint.setColor(DlColor::kDarkMagenta());
253 builder.DrawCircle(SkPoint{140, 170}, 75, paint);
254
255 paint.setColor(DlColor::kOrangeRed());
256 builder.DrawCircle(SkPoint{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 = DlImageFilter::MakeBlur(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() [35/494]

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

Definition at line 352 of file aiks_dl_blur_unittests.cc.

352 {
353 DisplayListBuilder builder;
354
355 DlPaint paint;
356 paint.setColor(DlColor::kGreen());
357 builder.DrawCircle(SkPoint{400, 400}, 300, paint);
358
359 DlPaint save_paint;
360 save_paint.setBlendMode(DlBlendMode::kSrc);
361
362 auto backdrop_filter =
363 DlImageFilter::MakeBlur(999999, 999999, DlTileMode::kClamp);
364 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
365 builder.Restore();
366
367 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
368 }

## ◆ TEST_P() [36/494]

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(SkPoint{100, 100}, 50, paint);
215
216 paint.setColor(DlColor::kGreenYellow());
217 builder.DrawCircle(SkPoint{300, 200}, 100, paint);
218
219 paint.setColor(DlColor::kDarkMagenta());
220 builder.DrawCircle(SkPoint{140, 170}, 75, paint);
221
222 paint.setColor(DlColor::kOrangeRed());
223 builder.DrawCircle(SkPoint{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 = DlImageFilter::MakeBlur(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() [37/494]

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

Definition at line 271 of file aiks_dl_blur_unittests.cc.

271 {
272 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
273
274 DisplayListBuilder builder;
275
276 DlPaint paint;
277 builder.DrawImage(image, SkPoint::Make(50.0, 50.0),
278 DlImageSampling::kNearestNeighbor, &paint);
279
280 SkRRect rrect =
281 SkRRect::MakeRectXY(SkRect::MakeXYWH(50, 250, 100, 100), 20, 20);
282 builder.Save();
283 builder.ClipRRect(rrect);
284
285 DlPaint save_paint;
286 save_paint.setBlendMode(DlBlendMode::kSrc);
287 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
288 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(),
289 /*backdrop_id=*/1);
290 builder.Restore();
291 builder.Restore();
292
293 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
294 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [38/494]

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

Definition at line 799 of file aiks_dl_basic_unittests.cc.

799 {
800 DisplayListBuilder builder;
801
802 builder.Scale(GetContentScale().x, GetContentScale().y);
803
804 // Draw something interesting in the background.
805 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
806 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
807 std::vector<Scalar> stops = {
808 0.0,
809 1.0,
810 };
811 DlPaint paint;
812 paint.setColorSource(DlColorSource::MakeLinear(
813 /*start_point=*/{0, 0}, //
814 /*end_point=*/{100, 100}, //
815 /*stop_count=*/2, //
816 /*colors=*/colors.data(), //
817 /*stops=*/stops.data(), //
818 /*tile_mode=*/DlTileMode::kRepeat //
819 ));
820
821 builder.DrawPaint(paint);
822
823 SkRect clip_rect = SkRect::MakeLTRB(50, 50, 400, 300);
824 SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 100, 100);
825
826 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
827 // the same.
828 builder.ClipRRect(clip_rrect, DlCanvas::ClipOp::kIntersect);
829
830 DlPaint save_paint;
831 auto backdrop_filter = DlImageFilter::MakeColorFilter(
832 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
833 builder.SaveLayer(&clip_rect, &save_paint, backdrop_filter.get());
834
835 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
836 }

References x.

## ◆ TEST_P() [39/494]

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

Definition at line 370 of file aiks_dl_blur_unittests.cc.

370 {
371 DisplayListBuilder builder;
372 builder.ClipRect(SkRect::MakeXYWH(100, 150, 400, 400));
373
374 DlPaint paint;
375 paint.setColor(DlColor::kGreen());
376 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
377 builder.DrawCircle(SkPoint{400, 400}, 200, paint);
378 builder.Restore();
379
380 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
381 }

## ◆ TEST_P() [40/494]

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

Definition at line 1419 of file aiks_dl_basic_unittests.cc.

1419 {
1420 DisplayListBuilder builder;
1421
1422 DlPaint paint;
1423 paint.setColor(DlColor::kWhite());
1424 builder.DrawPaint(paint);
1425
1426 // Draw a green circle on the screen.
1427 {
1428 // Increase the clip depth for the savelayer to contend with.
1429 SkPath path = SkPath::Circle(100, 100, 50);
1430 builder.ClipPath(path);
1431
1432 SkRect bounds = SkRect::MakeXYWH(50, 50, 100, 100);
1433 DlPaint save_paint;
1434 builder.SaveLayer(&bounds, &save_paint);
1435
1436 // Fill the layer with white.
1437 paint.setColor(DlColor::kWhite());
1438 builder.DrawRect(SkRect::MakeSize(SkSize{400, 400}), paint);
1439 // Fill the layer with green, but do so with a color blend that can't be
1440 // collapsed into the parent pass.
1441 paint.setColor(DlColor::kGreen());
1442 paint.setBlendMode(DlBlendMode::kHardLight);
1443 builder.DrawRect(SkRect::MakeSize(SkSize{400, 400}), paint);
1444 }
1445
1446 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1447 }

## ◆ TEST_P() [41/494]

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

Definition at line 42 of file aiks_dl_runtime_effect_unittests.cc.

42 {
43 struct FragUniforms {
44 Vector2 iResolution;
45 Scalar iTime;
46 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
47 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
48 uniform_data->resize(sizeof(FragUniforms));
49 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
50
51 DlPaint paint;
52 paint.setColorSource(
53 MakeRuntimeEffect(this, "runtime_stage_example.frag.iplr", uniform_data));
54
55 DisplayListBuilder builder;
56 builder.Save();
57 builder.ClipRRect(
58 SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 400, 400), 10.0, 10.0),
59 DlCanvas::ClipOp::kIntersect);
60 builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), paint);
61 builder.Restore();
62
63 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
64 }

## ◆ TEST_P() [42/494]

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

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() [44/494]

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 DlColorFilter::MakeBlend(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() [45/494]

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 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
88 paint.setInvertColors(true);
89
90 builder.DrawPaint(paint);
91 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
92 }

## ◆ TEST_P() [46/494]

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

Definition at line 667 of file aiks_dl_gradient_unittests.cc.

667 {
668 Scalar size = 256;
669 DisplayListBuilder builder;
670 DlPaint paint;
671 paint.setColor(DlColor::kWhite());
672 builder.DrawRect(SkRect::MakeXYWH(0, 0, size * 3, size * 3), paint);
673 std::vector<DlColor> colors = {
674 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
675 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
676 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
677 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
678 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
679 std::array<std::tuple<DlPoint, float, DlPoint, float>, 8> array{
680 std::make_tuple(DlPoint(size / 2.f, size / 2.f), 0.f,
681 DlPoint(size / 2.f, size / 2.f), size / 2.f),
682 std::make_tuple(DlPoint(size / 2.f, size / 2.f), size / 4.f,
683 DlPoint(size / 2.f, size / 2.f), size / 2.f),
684 std::make_tuple(DlPoint(size / 4.f, size / 4.f), 0.f,
685 DlPoint(size / 2.f, size / 2.f), size / 2.f),
686 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 2.f,
687 DlPoint(size / 2.f, size / 2.f), 0),
688 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 4.f,
689 DlPoint(size / 2.f, size / 2.f), size / 2.f),
690 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 16.f,
691 DlPoint(size / 2.f, size / 2.f), size / 8.f),
692 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 8.f,
693 DlPoint(size / 2.f, size / 2.f), size / 16.f),
694 std::make_tuple(DlPoint(size / 8.f, size / 8.f), size / 8.f,
695 DlPoint(size / 2.f, size / 2.f), size / 8.f),
696 };
697 for (int i = 0; i < 8; i++) {
698 builder.Save();
699 builder.Translate((i % 3) * size, i / 3 * size);
700 paint.setColorSource(DlColorSource::MakeConical(
701 std::get<2>(array[i]), std::get<3>(array[i]), std::get<0>(array[i]),
702 std::get<1>(array[i]), stops.size(), colors.data(), stops.data(),
703 DlTileMode::kClamp));
704 builder.DrawRect(SkRect::MakeXYWH(0, 0, size, size), paint);
705 builder.Restore();
706 }
707 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
708 }

## ◆ TEST_P() [47/494]

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

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

Definition at line 328 of file aiks_dl_gradient_unittests.cc.

328 {
329 CanRenderGradientWithIncompleteStops(this,
330 DlColorSourceType::kConicalGradient);
331 }

## ◆ TEST_P() [49/494]

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

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

Definition at line 389 of file aiks_dl_unittests.cc.

389 {
390 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
391
392 DlPaint paint;
393 paint.setColor(DlColor::kRed());
394 builder.DrawPaint(paint);
395 // Draw an empty savelayer with a destructive blend mode, which will replace
396 // the entire red screen with fully transparent black, except for the green
397 // circle drawn within the layer.
398
399 DlPaint save_paint;
400 save_paint.setBlendMode(DlBlendMode::kSrc);
401 builder.SaveLayer(nullptr, &save_paint);
402
403 DlPaint draw_paint;
404 draw_paint.setColor(DlColor::kGreen());
405 builder.DrawCircle(SkPoint{300, 300}, 100, draw_paint);
406 builder.Restore();
407
408 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
409 }

## ◆ TEST_P() [51/494]

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() [52/494]

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")),
172 SkPoint{10, 10}, {});
173 builder.DrawPath(path, paint);
174
175 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
176 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [53/494]

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

Definition at line 357 of file aiks_dl_basic_unittests.cc.

357 {
358 DisplayListBuilder builder;
359 DlPaint paint;
360
361 DlColor colors[2] = {
362 DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
363 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0),
364 };
365 DlScalar stops[2] = {
366 0.0,
367 1.0,
368 };
369
370 paint.setColorSource(DlColorSource::MakeLinear(
371 /*start_point=*/{0, 0}, //
372 /*end_point=*/{100, 100}, //
373 /*stop_count=*/2, //
374 /*colors=*/colors, //
375 /*stops=*/stops, //
376 /*tile_mode=*/DlTileMode::kRepeat //
377 ));
378
379 builder.Save();
380 builder.Translate(100, 100);
381 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
382 builder.Restore();
383
384 builder.Save();
385 builder.Translate(100, 400);
386 builder.DrawCircle(SkPoint{100, 100}, 100, paint);
387 builder.Restore();
388 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
389 }

## ◆ TEST_P() [54/494]

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

Definition at line 253 of file aiks_dl_text_unittests.cc.

253 {
254 DisplayListBuilder builder;
255
256 DlPaint paint;
257 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
258 builder.DrawPaint(paint);
259
260 ASSERT_TRUE(RenderTextInCanvasSkia(
261 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
262 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
263 }

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [55/494]

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

Definition at line 281 of file aiks_dl_text_unittests.cc.

281 {
282 DisplayListBuilder builder;
283
284 DlPaint paint;
285 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
286 builder.DrawPaint(paint);
287
288 ASSERT_TRUE(RenderTextInCanvasSkia(
289 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
290 {.color = DlColor::kBlack().modulateOpacity(0.5)}));
291 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
292 }

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [56/494]

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

Definition at line 265 of file aiks_dl_text_unittests.cc.

265 {
266 DisplayListBuilder builder;
267
268 builder.Scale(GetContentScale().x, GetContentScale().y);
269 DlPaint paint;
270 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
271 builder.DrawPaint(paint);
272
273 ASSERT_TRUE(RenderTextInCanvasSkia(
274 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
275 TextRenderOptions{
276 .color = DlColor::kBlue(),
277 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
278 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
279 }

References impeller::testing::TextRenderOptions::color, kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [57/494]

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 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kColor));
199 builder.DrawCircle(SkPoint{400, 400}, 200, paint);
200 builder.Restore();
201
202 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
203 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [58/494]

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 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kSrc));
179 builder.DrawCircle(SkPoint{400, 400}, 200, paint);
180
181 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
182 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [59/494]

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

Definition at line 710 of file aiks_dl_gradient_unittests.cc.

710 {
711 std::vector<DlColor> colors = {
712 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
713 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
714 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
715 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
716 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
717
718 std::array<std::shared_ptr<DlColorSource>, 3> color_sources = {
719 DlColorSource::MakeLinear({0, 0}, {100, 100}, stops.size(), colors.data(),
720 stops.data(), DlTileMode::kDecal),
721 DlColorSource::MakeRadial({100, 100}, 100, stops.size(), colors.data(),
722 stops.data(), DlTileMode::kDecal),
723 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
724 stops.data(), DlTileMode::kDecal),
725 };
726
727 DisplayListBuilder builder;
728 DlPaint paint;
729 paint.setColor(DlColor::kWhite());
730 builder.DrawRect(SkRect::MakeLTRB(0, 0, 605, 205), paint);
731 for (int i = 0; i < 3; i++) {
732 builder.Save();
733 builder.Translate(i * 200.0f, 0);
734 paint.setColorSource(color_sources[i]);
735 builder.DrawRect(SkRect::MakeLTRB(0, 0, 200, 200), paint);
736 builder.Restore();
737 }
738 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
739 }

## ◆ TEST_P() [60/494]

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() [61/494]

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() [62/494]

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

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

Definition at line 217 of file aiks_dl_basic_unittests.cc.

217 {
218 DisplayListBuilder builder;
219 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
220
221 SkSize image_half_size = SkSize::Make(image->dimensions().fWidth * 0.5f,
222 image->dimensions().fHeight * 0.5f);
223
224 // Render the bottom right quarter of the source image in a stretched rect.
225 auto source_rect = SkRect::MakeSize(image_half_size);
226 source_rect =
227 source_rect.makeOffset(image_half_size.fWidth, image_half_size.fHeight);
228
229 builder.DrawImageRect(image, source_rect,
230 SkRect::MakeXYWH(100, 100, 600, 600),
231 DlImageSampling::kNearestNeighbor);
232 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
233 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [64/494]

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 DlColorFilter::MakeBlend(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() [65/494]

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

Definition at line 233 of file aiks_dl_text_unittests.cc.

233 {
234 DisplayListBuilder builder;
235
236 DlPaint paint;
237 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
238 builder.DrawPaint(paint);
239
240 ASSERT_TRUE(RenderTextInCanvasSkia(
241 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
242 "HomemadeApple.ttf"));
243 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
244 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [66/494]

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

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

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(DlColorFilter::MakeBlend(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() [69/494]

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

Definition at line 373 of file aiks_dl_gradient_unittests.cc.

373 {
374 CanRenderLinearGradientManyColors(this, DlTileMode::kClamp);
375 }

## ◆ TEST_P() [70/494]

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

Definition at line 382 of file aiks_dl_gradient_unittests.cc.

382 {
383 CanRenderLinearGradientManyColors(this, DlTileMode::kDecal);
384 }

## ◆ TEST_P() [71/494]

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

Definition at line 379 of file aiks_dl_gradient_unittests.cc.

379 {
380 CanRenderLinearGradientManyColors(this, DlTileMode::kMirror);
381 }

## ◆ TEST_P() [72/494]

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

Definition at line 376 of file aiks_dl_gradient_unittests.cc.

376 {
377 CanRenderLinearGradientManyColors(this, DlTileMode::kRepeat);
378 }

## ◆ TEST_P() [73/494]

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

Definition at line 417 of file aiks_dl_gradient_unittests.cc.

417 {
418 auto callback = [&]() -> sk_sp<DisplayList> {
419 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
420 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
421 DlTileMode::kMirror, DlTileMode::kDecal};
422
423 static int selected_tile_mode = 0;
424 static Matrix matrix;
425 if (AiksTest::ImGuiBegin("Controls", nullptr,
426 ImGuiWindowFlags_AlwaysAutoResize)) {
427 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
428 sizeof(tile_mode_names) / sizeof(char*));
429 std::string label = "##1";
430 for (int i = 0; i < 4; i++) {
431 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
432 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
433 label[2]++;
434 }
435 ImGui::End();
436 }
437
438 DisplayListBuilder builder;
439 DlPaint paint;
440 builder.Translate(100.0, 100.0);
441 auto tile_mode = tile_modes[selected_tile_mode];
442
443 std::vector<DlColor> colors = {
444 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
445 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
446 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
447 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
448 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
449 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
450 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
451 std::vector<Scalar> stops = {
452 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
453 };
454
455 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
456 stops.size(), colors.data(),
457 stops.data(), tile_mode));
458
459 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
460 return builder.Build();
461 };
462 ASSERT_TRUE(OpenPlaygroundHere(callback));
463 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [74/494]

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

Definition at line 465 of file aiks_dl_gradient_unittests.cc.

465 {
466 DisplayListBuilder builder;
467
468 std::vector<DlColor> colors = {
469 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
470 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
471 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed()};
472 std::vector<Scalar> stops = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5,
473 0.6, 0.7, 0.8, 0.9, 1.0};
474
475 DlPaint paint;
476 paint.setColor(DlColor::kWhite());
477 paint.setColorSource(DlColorSource::MakeLinear(
478 {200, 200}, {400, 400}, stops.size(), colors.data(), stops.data(),
479 DlTileMode::kClamp));
480 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
481
482 builder.DrawCircle(SkPoint{300, 300}, 200, paint);
483 builder.DrawRect(SkRect::MakeLTRB(100, 300, 500, 600), paint);
484
485 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
486 }

## ◆ TEST_P() [75/494]

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

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

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

Definition at line 413 of file aiks_dl_gradient_unittests.cc.

413 {
414 CanRenderLinearGradientWayManyColors(this, DlTileMode::kClamp);
415 }

## ◆ TEST_P() [78/494]

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

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

Definition at line 320 of file aiks_dl_gradient_unittests.cc.

320 {
321 CanRenderGradientWithIncompleteStops(this,
322 DlColorSourceType::kLinearGradient);
323 }

## ◆ TEST_P() [80/494]

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

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(SkPoint{400, 400}, 300, paint);
160 builder.Restore();
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }

## ◆ TEST_P() [82/494]

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

Definition at line 296 of file aiks_dl_blur_unittests.cc.

296 {
297 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
298
299 DisplayListBuilder builder;
300
301 DlPaint paint;
302 builder.DrawImage(image, SkPoint::Make(50.0, 50.0),
303 DlImageSampling::kNearestNeighbor, &paint);
304
305 for (int i = 0; i < 6; i++) {
306 SkRRect rrect = SkRRect::MakeRectXY(
307 SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
308 builder.Save();
309 builder.ClipRRect(rrect);
310
311 DlPaint save_paint;
312 save_paint.setBlendMode(DlBlendMode::kSrc);
313 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
314 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(),
315 /*backdrop_id=*/1);
316 builder.Restore();
317 builder.Restore();
318 }
319
320 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
321 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [83/494]

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

Definition at line 323 of file aiks_dl_blur_unittests.cc.

324 {
325 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
326
327 DisplayListBuilder builder;
328
329 DlPaint paint;
330 builder.DrawImage(image, SkPoint::Make(50.0, 50.0),
331 DlImageSampling::kNearestNeighbor, &paint);
332
333 for (int i = 0; i < 6; i++) {
334 SkRRect rrect = SkRRect::MakeRectXY(
335 SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
336 builder.Save();
337 builder.ClipRRect(rrect);
338
339 DlPaint save_paint;
340 save_paint.setBlendMode(DlBlendMode::kSrc);
341 auto backdrop_filter =
342 DlImageFilter::MakeBlur(30 + i, 30, DlTileMode::kClamp);
343 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(),
344 /*backdrop_id=*/1);
345 builder.Restore();
346 builder.Restore();
347 }
348
349 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
350 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [84/494]

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

Definition at line 1365 of file aiks_dl_blur_unittests.cc.

1366 {
1367 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1368
1369 DisplayListBuilder builder;
1370
1371 DlPaint paint;
1372 builder.DrawImage(image, SkPoint::Make(50.0, 50.0),
1373 DlImageSampling::kNearestNeighbor, &paint);
1374
1375 for (int i = 0; i < 6; i++) {
1376 if (i != 0) {
1377 DlPaint paint;
1378 paint.setColor(DlColor::kWhite().withAlphaF(0.95));
1379 builder.SaveLayer(nullptr, &paint);
1380 }
1381 SkRRect rrect = SkRRect::MakeRectXY(
1382 SkRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
1383 builder.Save();
1384 builder.ClipRRect(rrect);
1385
1386 DlPaint save_paint;
1387 save_paint.setBlendMode(DlBlendMode::kSrc);
1388 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
1389 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get(),
1390 /*backdrop_id=*/1);
1391 builder.Restore();
1392 builder.Restore();
1393 if (i != 0) {
1394 builder.Restore();
1395 }
1396 }
1397
1398 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1399 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [85/494]

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

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

Definition at line 503 of file aiks_dl_path_unittests.cc.

503 {
504 DisplayListBuilder builder;
505
506 DlPaint paint;
507 paint.setColor(DlColor::kRed());
508
509 SkPoint radii[4] = {{50, 50}, {50, 50}, {50, 50}, {50, 50}};
510
511 const Scalar kTriangleHeight = 100;
512 SkRRect rrect;
513 rrect.setRectRadii(
514 SkRect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
515 kTriangleHeight, kTriangleHeight),
516 radii //
517 );
518
519 builder.Translate(200, 200);
520 // Form a path similar to the Material drop slider value indicator. Both
521 // shapes should render identically side-by-side.
522 {
523 SkPath path;
524 path.moveTo(0, kTriangleHeight);
525 path.lineTo(-kTriangleHeight / 2.0f, 0);
526 path.lineTo(kTriangleHeight / 2.0f, 0);
527 path.close();
528 path.addRRect(rrect);
529
530 builder.DrawPath(path, paint);
531 }
532 builder.Translate(100, 0);
533
534 {
535 SkPath path;
536 path.moveTo(0, kTriangleHeight);
537 path.lineTo(-kTriangleHeight / 2.0f, 0);
538 path.lineTo(0, -10);
539 path.lineTo(kTriangleHeight / 2.0f, 0);
540 path.close();
541 path.addRRect(rrect);
542
543 builder.DrawPath(path, paint);
544 }
545
546 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
547 }

## ◆ TEST_P() [87/494]

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

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

Definition at line 488 of file aiks_dl_gradient_unittests.cc.

488 {
489 auto callback = [&]() -> sk_sp<DisplayList> {
490 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
491 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
492 DlTileMode::kMirror, DlTileMode::kDecal};
493
494 static int selected_tile_mode = 0;
495 static Matrix matrix;
496 if (AiksTest::ImGuiBegin("Controls", nullptr,
497 ImGuiWindowFlags_AlwaysAutoResize)) {
498 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
499 sizeof(tile_mode_names) / sizeof(char*));
500 std::string label = "##1";
501 for (int i = 0; i < 4; i++) {
502 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
503 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
504 label[2]++;
505 }
506 ImGui::End();
507 }
508
509 DisplayListBuilder builder;
510 DlPaint paint;
511 builder.Translate(100.0, 100.0);
512 auto tile_mode = tile_modes[selected_tile_mode];
513
514 std::vector<DlColor> colors = {
515 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
516 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
517 std::vector<Scalar> stops = {0.0, 1.0};
518
519 paint.setColorSource(DlColorSource::MakeRadial(
520 {100, 100}, 100, 2, colors.data(), stops.data(), tile_mode));
521
522 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
523 return builder.Build();
524 };
525 ASSERT_TRUE(OpenPlaygroundHere(callback));
526 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [89/494]

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

Definition at line 528 of file aiks_dl_gradient_unittests.cc.

528 {
529 auto callback = [&]() -> sk_sp<DisplayList> {
530 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
531 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
532 DlTileMode::kMirror, DlTileMode::kDecal};
533
534 static int selected_tile_mode = 0;
535 static Matrix matrix = {
536 1, 0, 0, 0, //
537 0, 1, 0, 0, //
538 0, 0, 1, 0, //
539 0, 0, 0, 1 //
540 };
541 if (AiksTest::ImGuiBegin("Controls", nullptr,
542 ImGuiWindowFlags_AlwaysAutoResize)) {
543 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
544 sizeof(tile_mode_names) / sizeof(char*));
545 std::string label = "##1";
546 for (int i = 0; i < 4; i++) {
547 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
548 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
549 label[2]++;
550 }
551 ImGui::End();
552 }
553
554 DisplayListBuilder builder;
555 DlPaint paint;
556 builder.Translate(100.0, 100.0);
557 auto tile_mode = tile_modes[selected_tile_mode];
558
559 std::vector<DlColor> colors = {
560 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
561 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
562 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
563 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
564 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
565 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
566 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
567 std::vector<Scalar> stops = {
568 0.0,
569 (1.0 / 6.0) * 1,
570 (1.0 / 6.0) * 2,
571 (1.0 / 6.0) * 3,
572 (1.0 / 6.0) * 4,
573 (1.0 / 6.0) * 5,
574 1.0,
575 };
576
577 paint.setColorSource(DlColorSource::MakeRadial(
578 {100, 100}, 100, stops.size(), colors.data(), stops.data(), tile_mode));
579
580 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
581 return builder.Build();
582 };
583 ASSERT_TRUE(OpenPlaygroundHere(callback));
584 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [90/494]

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() [91/494]

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

Definition at line 324 of file aiks_dl_gradient_unittests.cc.

324 {
325 CanRenderGradientWithIncompleteStops(this,
326 DlColorSourceType::kRadialGradient);
327 }

## ◆ TEST_P() [92/494]

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

Definition at line 391 of file aiks_dl_basic_unittests.cc.

391 {
392 DisplayListBuilder builder;
393 DlPaint paint;
394 paint.setColor(DlColor::kRed());
395
396 SkRRect rrect;
397 SkVector radii[4] = {
398 SkVector{50, 25},
399 SkVector{25, 50},
400 SkVector{50, 25},
401 SkVector{25, 50},
402 };
403 rrect.setRectRadii(SkRect::MakeXYWH(100, 100, 500, 500), radii);
404
405 builder.DrawRRect(rrect, paint);
406
407 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
408 }

## ◆ TEST_P() [93/494]

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

Definition at line 87 of file aiks_dl_runtime_effect_unittests.cc.

87 {
88 auto runtime_stages =
89 OpenAssetAsRuntimeStage("runtime_stage_filter_example.frag.iplr");
90
91 std::shared_ptr<RuntimeStage> runtime_stage =
92 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
93 ASSERT_TRUE(runtime_stage);
94 ASSERT_TRUE(runtime_stage->IsDirty());
95
96 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
97 nullptr,
98 };
99 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
100 uniform_data->resize(sizeof(Vector2));
101
102 DlPaint paint;
103 paint.setColor(DlColor::kAqua());
104 paint.setImageFilter(DlImageFilter::MakeRuntimeEffect(
105 DlRuntimeEffect::MakeImpeller(runtime_stage), sampler_inputs,
106 uniform_data));
107
108 DisplayListBuilder builder;
109 builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), paint);
110
111 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
112 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [94/494]

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

Definition at line 255 of file aiks_dl_basic_unittests.cc.

255 {
256 DisplayListBuilder builder;
257 builder.Scale(GetContentScale().x, GetContentScale().y);
258 DlPaint paint;
259
260 paint.setColor(DlColor::kWhite());
261 builder.DrawPaint(paint);
262
263 auto draw = [&builder](const DlPaint& paint, Scalar x, Scalar y) {
264 builder.Save();
265 builder.Translate(x, y);
266 {
267 builder.Save();
268 builder.ClipRect(SkRect::MakeLTRB(50, 50, 150, 150));
269 builder.DrawPaint(paint);
270 builder.Restore();
271 }
272 {
273 builder.Save();
274 builder.ClipOval(SkRect::MakeLTRB(200, 50, 300, 150));
275 builder.DrawPaint(paint);
276 builder.Restore();
277 }
278 {
279 builder.Save();
280 builder.ClipRRect(
281 SkRRect::MakeRectXY(SkRect::MakeLTRB(50, 200, 150, 300), 20, 20));
282 builder.DrawPaint(paint);
283 builder.Restore();
284 }
285 {
286 builder.Save();
287 builder.ClipRRect(
288 SkRRect::MakeRectXY(SkRect::MakeLTRB(200, 230, 300, 270), 20, 20));
289 builder.DrawPaint(paint);
290 builder.Restore();
291 }
292 {
293 builder.Save();
294 builder.ClipRRect(
295 SkRRect::MakeRectXY(SkRect::MakeLTRB(230, 200, 270, 300), 20, 20));
296 builder.DrawPaint(paint);
297 builder.Restore();
298 }
299 builder.Restore();
300 };
301
302 paint.setColor(DlColor::kBlue());
303 draw(paint, 0, 0);
304
305 DlColor gradient_colors[7] = {
306 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
307 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
308 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
309 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
310 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
311 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
312 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
313 };
314 Scalar stops[7] = {
315 0.0,
316 (1.0 / 6.0) * 1,
317 (1.0 / 6.0) * 2,
318 (1.0 / 6.0) * 3,
319 (1.0 / 6.0) * 4,
320 (1.0 / 6.0) * 5,
321 1.0,
322 };
323 auto texture = CreateTextureForFixture("airplane.jpg",
324 /*enable_mipmapping=*/true);
325 auto image = DlImageImpeller::Make(texture);
326
327 paint.setColorSource(DlColorSource::MakeRadial(
328 {500, 600}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
329 draw(paint, 0, 300);
330
331 paint.setColorSource(
332 DlColorSource::MakeImage(image, DlTileMode::kRepeat, DlTileMode::kRepeat,
333 DlImageSampling::kNearestNeighbor));
334 draw(paint, 300, 0);
335
336 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
337 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [95/494]

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

Definition at line 114 of file aiks_dl_text_unittests.cc.

114 {
115 DisplayListBuilder builder;
116
117 DlPaint paint;
118 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
119 builder.DrawPaint(paint);
120
121 ASSERT_TRUE(RenderTextInCanvasSkia(
122 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
123 "Roboto-Regular.ttf",
124 {
125 .stroke = true,
126 }));
127 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
128 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [96/494]

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() [97/494]

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() [98/494]

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() [99/494]

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

Definition at line 607 of file aiks_dl_gradient_unittests.cc.

607 {
608 CanRenderSweepGradient(this, DlTileMode::kClamp);
609 }

## ◆ TEST_P() [100/494]

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

Definition at line 616 of file aiks_dl_gradient_unittests.cc.

616 {
617 CanRenderSweepGradient(this, DlTileMode::kDecal);
618 }

## ◆ TEST_P() [101/494]

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

Definition at line 654 of file aiks_dl_gradient_unittests.cc.

654 {
655 CanRenderSweepGradientManyColors(this, DlTileMode::kClamp);
656 }

## ◆ TEST_P() [102/494]

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

Definition at line 663 of file aiks_dl_gradient_unittests.cc.

663 {
664 CanRenderSweepGradientManyColors(this, DlTileMode::kDecal);
665 }

## ◆ TEST_P() [103/494]

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

Definition at line 660 of file aiks_dl_gradient_unittests.cc.

660 {
661 CanRenderSweepGradientManyColors(this, DlTileMode::kMirror);
662 }

## ◆ TEST_P() [104/494]

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

Definition at line 657 of file aiks_dl_gradient_unittests.cc.

657 {
658 CanRenderSweepGradientManyColors(this, DlTileMode::kRepeat);
659 }

## ◆ TEST_P() [105/494]

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

Definition at line 613 of file aiks_dl_gradient_unittests.cc.

613 {
614 CanRenderSweepGradient(this, DlTileMode::kMirror);
615 }

## ◆ TEST_P() [106/494]

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

Definition at line 610 of file aiks_dl_gradient_unittests.cc.

610 {
611 CanRenderSweepGradient(this, DlTileMode::kRepeat);
612 }

## ◆ TEST_P() [107/494]

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() [108/494]

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

Definition at line 332 of file aiks_dl_gradient_unittests.cc.

332 {
333 CanRenderGradientWithIncompleteStops(this, DlColorSourceType::kSweepGradient);
334 }

## ◆ TEST_P() [109/494]

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

Definition at line 85 of file aiks_dl_text_unittests.cc.

85 {
86 DisplayListBuilder builder;
87
88 DlPaint paint;
89 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
90 builder.DrawPaint(paint);
91 ASSERT_TRUE(RenderTextInCanvasSkia(
92 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
93 "Roboto-Regular.ttf"));
94
95 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
96 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [110/494]

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

Definition at line 160 of file aiks_dl_text_unittests.cc.

160 {
161 Scalar fine_scale = 0.f;
162 bool is_subpixel = false;
163 auto callback = [&]() -> sk_sp<DisplayList> {
164 if (AiksTest::ImGuiBegin("Controls", nullptr,
165 ImGuiWindowFlags_AlwaysAutoResize)) {
166 ImGui::SliderFloat("Fine Scale", &fine_scale, -1, 1);
167 ImGui::Checkbox("subpixel", &is_subpixel);
168 ImGui::End();
169 }
170
171 DisplayListBuilder builder;
172 DlPaint paint;
173 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
174 builder.DrawPaint(paint);
175 Scalar scale = 2.625 + fine_scale;
176 builder.Scale(scale, scale);
177 RenderTextInCanvasSkia(GetContext(), builder,
178 "the quick brown fox jumped over the lazy dog!.?",
179 "Roboto-Regular.ttf",
180 TextRenderOptions{.is_subpixel = is_subpixel});
181 return builder.Build();
182 };
183
184 ASSERT_TRUE(OpenPlaygroundHere(callback));
185 }

References impeller::testing::TextRenderOptions::is_subpixel, RenderTextInCanvasSkia(), and scale.

## ◆ TEST_P() [111/494]

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

Definition at line 146 of file aiks_dl_text_unittests.cc.

146 {
147 DisplayListBuilder builder;
148
149 DlPaint paint;
150 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
151 builder.DrawPaint(paint);
152 builder.Scale(0.5, 0.5);
153
154 ASSERT_TRUE(RenderTextInCanvasSkia(
155 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
156 "Roboto-Regular.ttf"));
157 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
158 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [112/494]

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

Definition at line 98 of file aiks_dl_text_unittests.cc.

98 {
99 DisplayListBuilder builder;
100
101 DlPaint paint;
102 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
103 builder.DrawPaint(paint);
104 builder.Translate(1000, 0);
105 builder.Scale(-1, 1);
106
107 ASSERT_TRUE(RenderTextInCanvasSkia(
108 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
109 "Roboto-Regular.ttf"));
110
111 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
112 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [113/494]

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

Definition at line 294 of file aiks_dl_text_unittests.cc.

294 {
295 DisplayListBuilder builder;
296
297 DlPaint paint;
298 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 0.1));
299 builder.DrawPaint(paint);
300
301 builder.Translate(100, 100);
302 builder.Scale(0.5, 0.5);
303
304 // Blend the layer with the parent pass using kClear to expose the coverage.
305 paint.setBlendMode(DlBlendMode::kClear);
306 builder.SaveLayer(nullptr, &paint);
307 ASSERT_TRUE(RenderTextInCanvasSkia(
308 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
309 "Roboto-Regular.ttf"));
310 builder.Restore();
311
312 // Render the text again over the cleared coverage rect.
313 ASSERT_TRUE(RenderTextInCanvasSkia(
314 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
315 "Roboto-Regular.ttf"));
316
317 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
318 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [114/494]

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

Definition at line 320 of file aiks_dl_text_unittests.cc.

320 {
321 DisplayListBuilder builder;
322 builder.Translate(200, 150);
323
324 // Construct the text blob.
325 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
326 ASSERT_NE(mapping, nullptr);
327
328 Scalar font_size = 80;
329 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
330 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
331
332 DlPaint text_paint;
333 text_paint.setColor(DlColor::kBlue().withAlpha(255 * 0.8));
334
335 struct {
336 SkPoint position;
337 const char* text;
338 } text[] = {{SkPoint::Make(0, 0), "0F0F0F0"},
339 {SkPoint::Make(1, 2), "789"},
340 {SkPoint::Make(1, 3), "456"},
341 {SkPoint::Make(1, 4), "123"},
342 {SkPoint::Make(0, 6), "0F0F0F0"}};
343 for (auto& t : text) {
344 builder.Save();
345 builder.Translate(t.position.x() * font_size * 2,
346 t.position.y() * font_size * 1.1);
347 {
348 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
349 ASSERT_NE(blob, nullptr);
350 auto frame = MakeTextFrameFromTextBlobSkia(blob);
351 builder.DrawTextFrame(frame, 0, 0, text_paint);
352 }
353 builder.Restore();
354 }
355
356 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
357 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [115/494]

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

Definition at line 130 of file aiks_dl_text_unittests.cc.

130 {
131 DisplayListBuilder builder;
132
133 DlPaint paint;
134 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
135 builder.DrawPaint(paint);
136
137 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "LMNOP VWXYZ",
138 "Roboto-Medium.ttf",
139 {
140 .stroke = true,
141 .stroke_width = 4,
142 }));
143 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
144 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [116/494]

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

Definition at line 418 of file aiks_dl_text_unittests.cc.

418 {
419 // Verifies that text scales are clamped to work around
420 // https://github.com/flutter/flutter/issues/136112 .
421
422 DisplayListBuilder builder;
423
424 DlPaint save_paint;
425 builder.SaveLayer(nullptr, &save_paint);
426 builder.Transform(SkM44::ColMajor(Matrix(2000, 0, 0, 0, //
427 0, 2000, 0, 0, //
428 0, 0, -1, 9000, //
429 0, 0, -1, 7000 //
430 )
431 .m));
432
433 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
434 "Roboto-Regular.ttf"));
435 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
436 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [117/494]

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

Definition at line 438 of file aiks_dl_text_unittests.cc.

438 {
439 DisplayListBuilder text_builder;
440 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), text_builder, "Hello world",
441 "Roboto-Regular.ttf"));
442 auto text_display_list = text_builder.Build();
443
444 DisplayListBuilder builder;
445
446 Matrix matrix = Matrix::MakeRow(2.0, 0.0, 0.0, 0.0, //
447 0.0, 2.0, 0.0, 0.0, //
448 0.0, 0.0, 1.0, 0.0, //
449 0.0, 0.002, 0.0, 1.0);
450
451 DlPaint save_paint;
452 SkRect window_bounds =
453 SkRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
454 builder.SaveLayer(&window_bounds, &save_paint);
455 builder.Transform(SkM44::ColMajor(matrix.m));
456 builder.DrawDisplayList(text_display_list, 1.0f);
457 builder.Restore();
458
459 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
460 }

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

## ◆ TEST_P() [118/494]

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() [119/494]

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() [120/494]

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

Definition at line 196 of file aiks_dl_basic_unittests.cc.

196 {
197 CanRenderTiledTexture(this, DlTileMode::kClamp);
198 }

## ◆ TEST_P() [121/494]

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

Definition at line 212 of file aiks_dl_basic_unittests.cc.

212 {
213 CanRenderTiledTexture(this, DlTileMode::kClamp,
214 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
215 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [122/494]

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

Definition at line 208 of file aiks_dl_basic_unittests.cc.

208 {
209 CanRenderTiledTexture(this, DlTileMode::kDecal);
210 }

## ◆ TEST_P() [123/494]

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

Definition at line 204 of file aiks_dl_basic_unittests.cc.

204 {
205 CanRenderTiledTexture(this, DlTileMode::kMirror);
206 }

## ◆ TEST_P() [124/494]

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

Definition at line 200 of file aiks_dl_basic_unittests.cc.

200 {
201 CanRenderTiledTexture(this, DlTileMode::kRepeat);
202 }

## ◆ TEST_P() [125/494]

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 364 of file aiks_dl_unittests.cc.

364 {
365 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
366
367 DlPaint paint;
368 paint.setColor(DlColor::kRed());
369 builder.DrawPaint(paint);
370
371 // Draw two overlapping subpixel circles.
372 builder.SaveLayer({});
373
374 DlPaint yellow_paint;
375 yellow_paint.setColor(DlColor::kYellow());
376 builder.DrawCircle(SkPoint{100, 100}, 0.1, yellow_paint);
377 builder.Restore();
378 builder.SaveLayer({});
379 builder.DrawCircle(SkPoint{100, 100}, 0.1, yellow_paint);
380 builder.Restore();
381
382 DlPaint draw_paint;
383 draw_paint.setColor(DlColor::kGreen());
384 builder.DrawPaint(draw_paint);
385
386 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
387 }

## ◆ TEST_P() [126/494]

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

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

Definition at line 339 of file aiks_dl_basic_unittests.cc.

339 {
340 DisplayListBuilder builder;
341
342 DlPaint red;
343 red.setColor(DlColor::kRed());
344
345 DlPaint alpha;
346 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
347
348 builder.SaveLayer(nullptr, &alpha);
349
350 builder.DrawCircle(SkPoint{125, 125}, 125, red);
351
352 builder.Restore();
353
354 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
355 }

## ◆ TEST_P() [128/494]

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

Definition at line 110 of file canvas_unittests.cc.

110 {
111 ContentContext context(GetContext(), nullptr);
112 auto canvas = CreateTestCanvas(context);
113
114 ASSERT_EQ(canvas->GetSaveCount(), 1u);
115 ASSERT_EQ(canvas->Restore(), false);
116
117 canvas->Translate(Size{100, 100});
118 canvas->Save(10);
119 ASSERT_EQ(canvas->GetSaveCount(), 2u);
120 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
121 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
122 ASSERT_TRUE(canvas->Restore());
123 ASSERT_EQ(canvas->GetSaveCount(), 1u);
124 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
125 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
126 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [129/494]

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

Definition at line 128 of file canvas_unittests.cc.

128 {
129 ContentContext context(GetContext(), nullptr);
130 auto canvas = CreateTestCanvas(context);
131
132 Matrix identity;
133 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), identity);
134 canvas->Translate(Size{100, 100});
135 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
136 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
137 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [130/494]

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

Definition at line 487 of file aiks_dl_blend_unittests.cc.

487 {
488 DisplayListBuilder builder;
489
490 DlPaint blue;
491 blue.setColor(DlColor::kBlue());
492 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600.0, 600.0), blue);
493
494 DlPaint clear;
495 clear.setBlendMode(DlBlendMode::kClear);
496
497 builder.DrawCircle(SkPoint{300.0, 300.0}, 200.0, clear);
498
499 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
500 }

## ◆ TEST_P() [131/494]

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

Definition at line 424 of file aiks_dl_blur_unittests.cc.

424 {
425 DisplayListBuilder builder;
426 DlPaint paint;
427 paint.setColor(DlColor::kBlue());
428 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600.0, 600.0), paint);
429
430 DlPaint clear;
431 clear.setBlendMode(DlBlendMode::kClear);
432 clear.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
433
434 builder.DrawCircle(SkPoint{300.0, 300.0}, 200.0, clear);
435
436 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
437 }

## ◆ TEST_P() [132/494]

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

Definition at line 1028 of file aiks_dl_basic_unittests.cc.

1028 {
1029 SetWindowSize({400, 400});
1030 DisplayListBuilder builder;
1031
1032 builder.Scale(GetContentScale().x, GetContentScale().y);
1033
1034 DlPaint paint;
1035 paint.setColor(DlColor::kRed());
1036 builder.DrawRect(SkRect::MakeLTRB(200, 200, 300, 300), paint);
1037
1038 paint.setImageFilter(DlImageFilter::MakeMatrix(DlMatrix::MakeScale({2, 2, 1}),
1039 DlImageSampling::kLinear));
1040 builder.SaveLayer(nullptr, &paint);
1041 // Draw a rectangle that would fully cover the parent pass size, but not
1042 // the subpass that it is rendered in.
1043 paint.setColor(DlColor::kGreen());
1044 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
1045 // Draw a bigger rectangle to force the subpass to be bigger.
1046
1047 paint.setColor(DlColor::kRed());
1048 builder.DrawRect(SkRect::MakeLTRB(0, 0, 800, 800), paint);
1049 builder.Restore();
1050
1051 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1052 }

References x.

## ◆ TEST_P() [133/494]

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

Definition at line 407 of file aiks_dl_blur_unittests.cc.

407 {
408 DisplayListBuilder builder;
409 builder.Translate(0, -400);
410 DlPaint paint;
411
412 Sigma sigma = Radius{120 * 3};
413 paint.setMaskFilter(
414 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
415 paint.setColor(DlColor::kRed());
416
417 SkPath path = SkPath::Rect(SkRect::MakeLTRB(0, 0, 800, 800));
418 path.addCircle(0, 0, 0.5);
419 builder.DrawPath(path, paint);
420
421 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
422 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [134/494]

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

Definition at line 383 of file aiks_dl_blur_unittests.cc.

383 {
384 auto callback = [&]() -> sk_sp<DisplayList> {
385 static PlaygroundPoint playground_point(Point(400, 400), 20,
386 Color::Green());
387 auto point = DrawPlaygroundPoint(playground_point);
388
389 DisplayListBuilder builder;
390 auto location = point - Point(400, 400);
391 builder.Translate(location.x, location.y);
392
393 DlPaint paint;
394 Sigma sigma = Radius{120 * 3};
395 paint.setMaskFilter(
396 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
397 paint.setColor(DlColor::kRed());
398
399 SkPath path = SkPath::Rect(SkRect::MakeLTRB(0, 0, 800, 800));
400 path.addCircle(0, 0, 0.5);
401 builder.DrawPath(path, paint);
402 return builder.Build();
403 };
404 ASSERT_TRUE(OpenPlaygroundHere(callback));
405 }

References impeller::DrawPlaygroundPoint(), impeller::Color::Green(), and impeller::Sigma::sigma.

## ◆ TEST_P() [135/494]

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() [136/494]

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

Definition at line 48 of file aiks_dl_unittests.cc.

48 {
49 DisplayListBuilder builder;
50
51 DlPaint paint;
52 paint.setColor(DlColor::kYellow());
53 paint.setBlendMode(DlBlendMode::kSrc);
54 builder.DrawPaint(paint);
55
56 DlPaint save_paint;
57 save_paint.setBlendMode(DlBlendMode::kMultiply);
58 builder.SaveLayer(nullptr, &save_paint);
59
60 DlPaint draw_paint;
61 draw_paint.setColor(DlColor::kCornflowerBlue().modulateOpacity(0.75f));
62 builder.DrawPaint(draw_paint);
63
64 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
65 }

## ◆ TEST_P() [137/494]

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

Definition at line 67 of file aiks_dl_unittests.cc.

67 {
68 // Bug: https://github.com/flutter/flutter/issues/131576
69 DisplayListBuilder builder;
70
71 DlPaint paint;
72 paint.setColor(DlColor::kYellow());
73 paint.setBlendMode(DlBlendMode::kSrc);
74 builder.DrawPaint(paint);
75
76 auto filter = DlImageFilter::MakeBlur(20.0, 20.0, DlTileMode::kDecal);
77 builder.SaveLayer(nullptr, nullptr, filter.get());
78
79 DlPaint draw_paint;
80 draw_paint.setColor(DlColor::kCornflowerBlue());
81 builder.DrawPaint(draw_paint);
82
83 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
84 }

## ◆ TEST_P() [138/494]

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, SkPoint{0, 0},
286 DlImageSampling::kMipmapLinear, &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 DlColorFilter::MakeBlend(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
294 DlBlendMode::kSrcIn);
295 srcPaint.setColorFilter(color_filter);
296 }
297 builder.DrawImage(src_image, SkPoint{0, 0},
298 DlImageSampling::kMipmapLinear, &srcPaint);
299 }
300 builder.Restore();
301 }
302 return builder.Build();
303 };
304 ASSERT_TRUE(OpenPlaygroundHere(callback));
305 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [139/494]

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 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsPrimitiveRestart);
342 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
343
344 bool has_color_filter = true;
345 auto callback = [&]() -> sk_sp<DisplayList> {
346 if (AiksTest::ImGuiBegin("Controls", nullptr,
347 ImGuiWindowFlags_AlwaysAutoResize)) {
348 ImGui::Checkbox("has color filter", &has_color_filter);
349 ImGui::End();
350 }
351
352 DisplayListBuilder builder;
353 builder.Scale(GetContentScale().x, GetContentScale().y);
354
355 auto src_image =
356 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
357 auto dst_image =
358 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
359
360 std::vector<DlBlendMode> blend_modes = {
361 DlBlendMode::kScreen, DlBlendMode::kOverlay,
362 DlBlendMode::kDarken, DlBlendMode::kLighten,
363 DlBlendMode::kColorDodge, DlBlendMode::kColorBurn,
364 DlBlendMode::kHardLight, DlBlendMode::kSoftLight,
365 DlBlendMode::kDifference, DlBlendMode::kExclusion,
366 DlBlendMode::kMultiply, DlBlendMode::kHue,
367 DlBlendMode::kSaturation, DlBlendMode::kColor,
368 DlBlendMode::kLuminosity,
369 };
370
371 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
372 builder.Save();
373 builder.Translate((i % 5) * 200, (i / 5) * 200);
374 builder.Scale(0.4, 0.4);
375 {
376 DlPaint dstPaint;
377 builder.DrawImage(dst_image, SkPoint{0, 0},
378 DlImageSampling::kMipmapLinear, &dstPaint);
379 }
380 {
381 DlPaint srcPaint;
382 srcPaint.setBlendMode(blend_modes[i]);
383 if (has_color_filter) {
384 std::shared_ptr<const DlColorFilter> color_filter =
385 DlColorFilter::MakeBlend(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
386 DlBlendMode::kMultiply);
387 srcPaint.setColorFilter(color_filter);
388 }
389 builder.DrawImage(src_image, SkPoint{0, 0},
390 DlImageSampling::kMipmapLinear, &srcPaint);
391 }
392 builder.Restore();
393 }
394 return builder.Build();
395 };
396 ASSERT_TRUE(OpenPlaygroundHere(callback));
397 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::kMetal, impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [140/494]

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, SkPoint{0, 0},
229 DlImageSampling::kMipmapLinear, &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 DlColorFilter::MakeBlend(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
237 DlBlendMode::kSrcIn);
238 srcPaint.setColorFilter(color_filter);
239 }
240 builder.DrawImage(src_image, SkPoint{0, 0},
241 DlImageSampling::kMipmapLinear, &srcPaint);
242 }
243 builder.Restore();
244 }
245 return builder.Build();
246 };
247 ASSERT_TRUE(OpenPlaygroundHere(callback));
248 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [141/494]

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

Definition at line 86 of file aiks_dl_unittests.cc.

86 {
87 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
88
89 const float matrix[20] = {
90 -1.0, 0, 0, 1.0, 0, //
91 0, -1.0, 0, 1.0, 0, //
92 0, 0, -1.0, 1.0, 0, //
93 1.0, 1.0, 1.0, 1.0, 0 //
94 };
95 auto filter = DlColorFilter::MakeMatrix(matrix);
96
97 DlPaint paint;
98 paint.setColorFilter(filter);
99 builder.SaveLayer(nullptr, &paint);
100
101 builder.Translate(500, 300);
102 builder.Rotate(120); // 120 deg
103
104 DlPaint draw_paint;
105 draw_paint.setColor(DlColor::kBlue());
106 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
107
108 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
109 }

## ◆ TEST_P() [142/494]

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 775 of file aiks_dl_blend_unittests.cc.

775 {
776 // Compare with https://fiddle.skia.org/c/@BlendModes
777
778 BlendModeSelection blend_modes = GetBlendModeSelection();
779
780 auto draw_color_wheel = [](DisplayListBuilder& builder) -> void {
781 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
782 /// cyan domain: r >= 0 (because modulo used is non euclidean)
783 auto color_wheel_sampler = [](Radians r) {
784 Scalar x = r.radians / k2Pi + 1;
785
786 // https://www.desmos.com/calculator/6nhjelyoaj
787 auto color_cycle = [](Scalar x) {
788 Scalar cycle = std::fmod(x, 6.0f);
789 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
790 };
791 return Color(color_cycle(6 * x + 1), //
792 color_cycle(6 * x - 1), //
793 color_cycle(6 * x - 3), //
794 1);
795 };
796
797 DlPaint paint;
798 paint.setBlendMode(DlBlendMode::kSrcOver);
799
800 // Draw a fancy color wheel for the backdrop.
801 // https://www.desmos.com/calculator/xw7kafthwd
802 const int max_dist = 900;
803 for (int i = 0; i <= 900; i++) {
804 Radians r(kPhi / k2Pi * i);
805 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
806 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
807
808 auto color = color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
809 paint.setColor(
810 DlColor::RGBA(color.red, color.green, color.blue, color.alpha));
811 SkPoint position = SkPoint::Make(distance * std::sin(r.radians),
812 -distance * std::cos(r.radians));
813
814 builder.DrawCircle(position, 9 + normalized_distance * 3, paint);
815 }
816 };
817
818 auto callback = [&]() -> sk_sp<DisplayList> {
819 // UI state.
820 static bool cache_the_wheel = true;
821 static int current_blend_index = 3;
822 static float dst_alpha = 1;
823 static float src_alpha = 1;
824 static DlColor color0 = DlColor::kRed();
825 static DlColor color1 = DlColor::kGreen();
826 static DlColor color2 = DlColor::kBlue();
827
828 if (AiksTest::ImGuiBegin("Controls", nullptr,
829 ImGuiWindowFlags_AlwaysAutoResize)) {
830 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
831 ImGui::ListBox("Blending mode", &current_blend_index,
832 blend_modes.blend_mode_names.data(),
833 blend_modes.blend_mode_names.size());
834 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
835 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
836 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
837 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
838 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
839 ImGui::End();
840 }
841
842 DisplayListBuilder builder;
843
844 DlPaint paint;
845 paint.setColor(DlColor::kWhite().withAlpha(dst_alpha * 255));
846 paint.setBlendMode(DlBlendMode::kSrc);
847 builder.SaveLayer(nullptr, &paint);
848 {
849 DlPaint paint;
850 paint.setColor(DlColor::kWhite());
851 builder.DrawPaint(paint);
852
853 builder.SaveLayer(nullptr, nullptr);
854 builder.Scale(GetContentScale().x, GetContentScale().y);
855 builder.Translate(500, 400);
856 builder.Scale(3, 3);
857 draw_color_wheel(builder);
858 builder.Restore();
859 }
860 builder.Restore();
861
862 builder.Scale(GetContentScale().x, GetContentScale().y);
863 builder.Translate(500, 400);
864 builder.Scale(3, 3);
865
866 // Draw 3 circles to a subpass and blend it in.
867 DlPaint save_paint;
868 save_paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
869 save_paint.setBlendMode(static_cast<DlBlendMode>(
870 blend_modes.blend_mode_values[current_blend_index]));
871 builder.SaveLayer(nullptr, &save_paint);
872 {
873 DlPaint paint;
874 paint.setBlendMode(DlBlendMode::kPlus);
875 const Scalar x = std::sin(k2Pi / 3);
876 const Scalar y = -std::cos(k2Pi / 3);
877 paint.setColor(color0);
878 builder.DrawCircle(SkPoint::Make(-x * 45, y * 45), 65, paint);
879 paint.setColor(color1);
880 builder.DrawCircle(SkPoint::Make(0, -45), 65, paint);
881 paint.setColor(color2);
882 builder.DrawCircle(SkPoint::Make(x * 45, y * 45), 65, paint);
883 }
884 builder.Restore();
885
886 return builder.Build();
887 };
888
889 ASSERT_TRUE(OpenPlaygroundHere(callback));
890 }

References impeller::testing::BlendModeSelection::blend_mode_names, impeller::testing::BlendModeSelection::blend_mode_values, impeller::saturated::distance, GetBlendModeSelection(), impeller::AiksPlayground::ImGuiBegin(), impeller::k2Pi, impeller::kPhi, impeller::Radians::radians, and x.

## ◆ TEST_P() [143/494]

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

Definition at line 1126 of file aiks_dl_basic_unittests.cc.

1126 {
1127 DisplayListBuilder builder;
1128
1129 // Render a texture directly.
1130 {
1131 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1132
1133 builder.Save();
1134 builder.Translate(100, 200);
1135 builder.Scale(0.5, 0.5);
1136 builder.DrawImage(image, SkPoint::Make(100.0, 100.0),
1137 DlImageSampling::kNearestNeighbor);
1138 builder.Restore();
1139 }
1140
1141 // Render an offscreen rendered texture.
1142 {
1143 DlPaint alpha;
1144 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1145
1146 builder.SaveLayer(nullptr, &alpha);
1147
1148 DlPaint paint;
1149 paint.setColor(DlColor::kRed());
1150 builder.DrawRect(SkRect::MakeXYWH(000, 000, 100, 100), paint);
1151 paint.setColor(DlColor::kGreen());
1152 builder.DrawRect(SkRect::MakeXYWH(020, 020, 100, 100), paint);
1153 paint.setColor(DlColor::kBlue());
1154 builder.DrawRect(SkRect::MakeXYWH(040, 040, 100, 100), paint);
1155
1156 builder.Restore();
1157 }
1158
1159 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1160 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [144/494]

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

Definition at line 1309 of file aiks_dl_basic_unittests.cc.

1309 {
1310 auto callback = [&]() -> sk_sp<DisplayList> {
1311 DisplayListBuilder builder;
1312 builder.Scale(GetContentScale().x, GetContentScale().y);
1313
1314 DlPaint alpha;
1315 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1316
1317 auto current = Point{25, 25};
1318 const auto offset = Point{25, 25};
1319 const auto size = Size(100, 100);
1320
1321 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1322 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1323 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1324 SkRect bounds = SkRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1325
1326 DlPaint stroke_paint;
1327 stroke_paint.setColor(DlColor::kYellow());
1328 stroke_paint.setStrokeWidth(5);
1329 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1330 builder.DrawRect(bounds, stroke_paint);
1331
1332 builder.SaveLayer(&bounds, &alpha);
1333
1334 DlPaint paint;
1335 paint.setColor(DlColor::kRed());
1336 builder.DrawRect(
1337 SkRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1338
1339 paint.setColor(DlColor::kGreen());
1340 current += offset;
1341 builder.DrawRect(
1342 SkRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1343
1344 paint.setColor(DlColor::kBlue());
1345 current += offset;
1346 builder.DrawRect(
1347 SkRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1348
1349 builder.Restore();
1350
1351 return builder.Build();
1352 };
1353
1354 ASSERT_TRUE(OpenPlaygroundHere(callback));
1355 }

References impeller::DrawPlaygroundLine(), offset, and impeller::Color::White().

## ◆ TEST_P() [145/494]

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

Definition at line 993 of file aiks_dl_unittests.cc.

993 {
994 // Ensures that the additional draws created by line/polygon mode all
995 // have the same depth values.
996 DisplayListBuilder builder;
997
998 SkPath path = SkPath::Circle(100, 100, 100);
999
1000 builder.DrawPath(path, DlPaint()
1001 .setColor(DlColor::kRed())
1002 .setDrawStyle(DlDrawStyle::kStroke)
1003 .setStrokeWidth(5));
1004 builder.Save();
1005 builder.ClipPath(path);
1006
1007 std::vector<DlPoint> points = {
1008 DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1009 DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1010 DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1011 DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1012 DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1013
1014 builder.DrawPoints(DisplayListBuilder::PointMode::kLines, points.size(),
1015 points.data(),
1016 DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1017 builder.Restore();
1018
1019 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1020 }

## ◆ TEST_P() [146/494]

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

Definition at line 1022 of file aiks_dl_unittests.cc.

1022 {
1023 // Ensures that the additional draws created by line/polygon mode all
1024 // have the same depth values.
1025 DisplayListBuilder builder;
1026
1027 SkPath path = SkPath::Circle(100, 100, 100);
1028
1029 builder.DrawPath(path, DlPaint()
1030 .setColor(DlColor::kRed())
1031 .setDrawStyle(DlDrawStyle::kStroke)
1032 .setStrokeWidth(5));
1033 builder.Save();
1034 builder.ClipPath(path);
1035
1036 std::vector<DlPoint> points = {
1037 DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1038 DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1039 DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1040 DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1041 DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1042
1043 builder.DrawPoints(DisplayListBuilder::PointMode::kPolygon, points.size(),
1044 points.data(),
1045 DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1046 builder.Restore();
1047
1048 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1049 }

## ◆ TEST_P() [147/494]

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

Definition at line 892 of file aiks_dl_blend_unittests.cc.

892 {
893 DisplayListBuilder builder;
894
895 DlPaint paint;
896 paint.setColor(DlColor::kBlue());
897 builder.DrawPaint(paint);
898
899 DlPaint save_paint;
900 save_paint.setColorFilter(
901 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kSrc));
902 builder.SaveLayer(nullptr, &save_paint);
903 builder.Restore();
904
905 // Should be solid red as the destructive color filter floods the clip.
906 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
907 }

## ◆ TEST_P() [148/494]

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

Definition at line 504 of file aiks_dl_text_unittests.cc.

504 {
505 DisplayListBuilder builder;
506
507 DlPaint paint;
508 DlColor clear_color(1.0, 0.5, 0.5, 0.5, DlColorSpace::kSRGB);
509 paint.setColor(clear_color);
510 builder.DrawPaint(paint);
511
512 DlMatrix identity = {
513 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
514 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
515 };
516 builder.Save();
517 builder.Transform(identity);
518
519 DlRect frame = DlRect::MakeLTRB(1.0, 1.0, 1278.0, 763.0);
520 DlColor white(1.0, 1.0, 1.0, 1.0, DlColorSpace::kSRGB);
521 paint.setColor(white);
522 builder.DrawRect(frame, paint);
523
524 builder.Save();
525 builder.ClipRect(frame, DlCanvas::ClipOp::kIntersect);
526
527 DlMatrix rect_xform = {
528 0.8241262, 0.56640625, 0.0, 0.0, -0.56640625, 0.8241262, 0.0, 0.0,
529 0.0, 0.0, 1.0, 0.0, 271.1137, 489.4733, 0.0, 1.0,
530 };
531 builder.Save();
532 builder.Transform(rect_xform);
533
534 DlRect rect = DlRect::MakeLTRB(0.0, 0.0, 100.0, 100.0);
535 DlColor bluish(1.0, 0.184, 0.501, 0.929, DlColorSpace::kSRGB);
536 paint.setColor(bluish);
537 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 18.0);
538 builder.DrawRoundRect(rrect, paint);
539
540 builder.Save();
541 builder.ClipRect(rect, DlCanvas::ClipOp::kIntersect);
542 builder.Restore();
543
544 builder.Restore();
545
546 DlMatrix path_xform = {
547 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
548 0.0, 0.0, 1.0, 0.0, 675.0, 279.5, 0.0, 1.0,
549 };
550 builder.Save();
551 builder.Transform(path_xform);
552
553 SkPath path;
554 path.moveTo(87.5, 349.5);
555 path.lineTo(25.0, 29.5);
556 path.lineTo(150.0, 118.0);
557 path.lineTo(25.0, 118.0);
558 path.lineTo(150.0, 29.5);
559 path.close();
560
561 DlColor fill_color(1.0, 1.0, 0.0, 0.0, DlColorSpace::kSRGB);
562 DlColor stroke_color(1.0, 0.0, 0.0, 0.0, DlColorSpace::kSRGB);
563 paint.setColor(fill_color);
564 paint.setDrawStyle(DlDrawStyle::kFill);
565 builder.DrawPath(DlPath(path), paint);
566
567 paint.setColor(stroke_color);
568 paint.setStrokeWidth(2.0);
569 paint.setDrawStyle(DlDrawStyle::kStroke);
570 builder.DrawPath(path, paint);
571
572 builder.Restore();
573 builder.Restore();
574 builder.Restore();
575
576 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
577 }

## ◆ TEST_P() [149/494]

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

Definition at line 879 of file aiks_dl_unittests.cc.

879 {
880 flutter::DisplayListBuilder sub_builder(true);
881 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
882 flutter::DlPaint(flutter::DlColor::kRed()));
883 auto display_list = sub_builder.Build();
884
885 AiksContext context(GetContext(), nullptr);
886 RenderTarget render_target =
887 context.GetContentContext().GetRenderTargetCache()->CreateOffscreen(
888 *context.GetContext(), {2400, 1800}, 1);
889
890 DisplayListBuilder builder;
891
892 builder.Scale(2.0, 2.0);
893 builder.Translate(-93.0, 0.0);
894
895 // clang-format off
896 builder.TransformFullPerspective(
897 0.8, -0.2, -0.1, -0.0,
898 0.0, 1.0, 0.0, 0.0,
899 1.4, 1.3, 1.0, 0.0,
900 63.2, 65.3, 48.6, 1.1
901 );
902 // clang-format on
903 builder.Translate(35.0, 75.0);
904 builder.DrawDisplayList(display_list, 1.0f);
905
906 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
907 }

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

## ◆ TEST_P() [150/494]

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

Definition at line 198 of file aiks_dl_atlas_unittests.cc.

198 {
199 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
200
201 std::vector<DlColor> colors;
202 colors.reserve(texture_coordinates.size());
203 for (auto i = 0u; i < texture_coordinates.size(); i++) {
204 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
205 }
206 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
207 texture_coordinates.data(), colors.data(),
208 transforms.size(), BlendMode::kSourceOver, {},
209 std::nullopt);
210
211 EXPECT_TRUE(geom.ShouldUseBlend());
212 EXPECT_FALSE(geom.ShouldSkip());
213
214 ContentContext context(GetContext(), nullptr);
215 auto vertex_buffer =
216 geom.CreateBlendVertexBuffer(context.GetTransientsBuffer());
217
218 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
219 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
220 }

References impeller::DlAtlasGeometry::CreateBlendVertexBuffer(), impeller::ContentContext::GetTransientsBuffer(), impeller::kNone, impeller::kSourceOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [151/494]

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

Definition at line 222 of file aiks_dl_atlas_unittests.cc.

222 {
223 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
224
225 std::vector<DlColor> colors;
226 colors.reserve(texture_coordinates.size());
227 for (auto i = 0u; i < texture_coordinates.size(); i++) {
228 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
229 }
230 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
231 texture_coordinates.data(), colors.data(),
232 transforms.size(), BlendMode::kSource, {}, std::nullopt);
233
234 // Src blend mode means that colors would be ignored, even if provided.
235 EXPECT_FALSE(geom.ShouldUseBlend());
236 EXPECT_FALSE(geom.ShouldSkip());
237 }

References impeller::kSource, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [152/494]

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

Definition at line 180 of file aiks_dl_atlas_unittests.cc.

180 {
181 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
182
183 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
184 texture_coordinates.data(), nullptr, transforms.size(),
185 BlendMode::kSourceOver, {}, std::nullopt);
186
187 EXPECT_FALSE(geom.ShouldUseBlend());
188 EXPECT_FALSE(geom.ShouldSkip());
189
190 ContentContext context(GetContext(), nullptr);
191 auto vertex_buffer =
192 geom.CreateSimpleVertexBuffer(context.GetTransientsBuffer());
193
194 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
195 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
196 }

References impeller::DlAtlasGeometry::CreateSimpleVertexBuffer(), impeller::ContentContext::GetTransientsBuffer(), impeller::kNone, impeller::kSourceOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [153/494]

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

Definition at line 239 of file aiks_dl_atlas_unittests.cc.

239 {
240 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
241
242 std::vector<DlColor> colors;
243 colors.reserve(texture_coordinates.size());
244 for (auto i = 0u; i < texture_coordinates.size(); i++) {
245 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
246 }
247 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
248 texture_coordinates.data(), colors.data(),
249 transforms.size(), BlendMode::kClear, {}, std::nullopt);
250 EXPECT_TRUE(geom.ShouldSkip());
251 }

References impeller::kClear, and impeller::DlAtlasGeometry::ShouldSkip().

## ◆ TEST_P() [154/494]

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 DlMatrix matrix = DlMatrix::MakeScale({0.3, 0.3, 1.0});
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(SkPoint{100, 100}, 100, paint);
170 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
171 }

## ◆ TEST_P() [155/494]

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

Definition at line 134 of file aiks_dl_atlas_unittests.cc.

134 {
135 DisplayListBuilder builder;
136 // Draws the image as four squares stiched together.
137 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
138
139 builder.Scale(0.25, 0.25);
140 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
141 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kModulate,
142 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
143
144 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
145 }

## ◆ TEST_P() [156/494]

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

Definition at line 57 of file aiks_dl_atlas_unittests.cc.

57 {
58 DisplayListBuilder builder;
59 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
60
61 builder.Scale(GetContentScale().x, GetContentScale().y);
62 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
63 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kSrcOver,
64 DlImageSampling::kNearestNeighbor, nullptr);
65
66 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
67 }

References x.

## ◆ TEST_P() [157/494]

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

Definition at line 117 of file aiks_dl_atlas_unittests.cc.

117 {
118 auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
119 auto size = atlas->impeller_texture()->GetSize();
120 std::vector<DlRect> texture_coordinates = {
121 DlRect::MakeLTRB(0, 0, size.width, size.height)};
122 std::vector<RSTransform> transforms = {MakeTranslation(0, 0)};
123
124 DisplayListBuilder builder;
125 builder.Scale(GetContentScale().x, GetContentScale().y);
126 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
127 /*colors=*/nullptr, /*count=*/1, DlBlendMode::kSrcOver,
128 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
129
130 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
131 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [158/494]

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

Definition at line 163 of file aiks_dl_atlas_unittests.cc.

163 {
164 DisplayListBuilder builder;
165 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
166 PixelFormat::kB10G10R10A10XR);
167
168 // Draws the image as four squares stiched together.
169 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
170 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
171 DlColor::kBlue(), DlColor::kYellow()};
172
173 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
174 colors.data(), /*count=*/4, DlBlendMode::kPlus,
175 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
176
177 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
178 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [159/494]

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

Definition at line 69 of file aiks_dl_atlas_unittests.cc.

69 {
70 DisplayListBuilder builder;
71 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
72
73 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
74 DlColor::kBlue(), DlColor::kYellow()};
75
76 builder.Scale(GetContentScale().x, GetContentScale().y);
77 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
78 colors.data(), /*count=*/4, DlBlendMode::kModulate,
79 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
80
81 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
82 }

References x.

## ◆ TEST_P() [160/494]

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

Definition at line 148 of file aiks_dl_atlas_unittests.cc.

148 {
149 DisplayListBuilder builder;
150 // Draws the image as four squares stiched together.
151 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
152 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
153 DlColor::kBlue(), DlColor::kYellow()};
154
155 builder.Scale(0.25, 0.25);
156 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
157 colors.data(), /*count=*/4, DlBlendMode::kModulate,
158 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
159
160 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
161 }

## ◆ TEST_P() [161/494]

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

Definition at line 84 of file aiks_dl_atlas_unittests.cc.

84 {
85 DisplayListBuilder builder;
86 // Draws the image as four squares stiched together.
87 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
88
89 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
90 DlColor::kBlue(), DlColor::kYellow()};
91
92 builder.Scale(GetContentScale().x, GetContentScale().y);
93 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
94 colors.data(), /*count=*/4, DlBlendMode::kSrcATop,
95 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
96
97 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
98 }

References x.

## ◆ TEST_P() [162/494]

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

Definition at line 100 of file aiks_dl_atlas_unittests.cc.

100 {
101 DisplayListBuilder builder;
102 // Draws the image as four squares stiched together slightly
103 // opaque
104 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
105
106 DlPaint paint;
107 paint.setAlpha(128);
108 builder.Scale(GetContentScale().x, GetContentScale().y);
109 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
110 /*colors=*/nullptr, 4, DlBlendMode::kSrcOver,
111 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr,
112 &paint);
113
114 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
115 }

References x.

## ◆ TEST_P() [163/494]

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

Definition at line 235 of file aiks_dl_basic_unittests.cc.

235 {
236 DisplayListBuilder builder;
237 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
238
239 // Use a source rect that is partially outside the bounds of the image.
240 auto source_rect = SkRect::MakeXYWH(
241 image->dimensions().fWidth * 0.25f, image->dimensions().fHeight * 0.4f,
242 image->dimensions().fWidth, image->dimensions().fHeight);
243
244 auto dest_rect = SkRect::MakeXYWH(100, 100, 600, 600);
245
246 DlPaint paint;
247 paint.setColor(DlColor::kMidGrey());
248 builder.DrawRect(dest_rect, paint);
249
250 builder.DrawImageRect(image, source_rect, dest_rect,
251 DlImageSampling::kNearestNeighbor);
252 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
253 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [164/494]

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(SkPoint{150, 100}, SkPoint{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(SkPoint{100, 150}, SkPoint{100, 250}, paint);
333 builder.DrawCircle({origin}, 35, paint);
334
335 builder.DrawLine(SkPoint{250, 250}, SkPoint{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 DlMatrix matrix = DlMatrix::MakeTranslation({-150, 75});
372 paint.setColorSource(DlColorSource::MakeImage(
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(), impeller::Matrix::MakeRotationZ(), and x.

## ◆ TEST_P() [165/494]

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

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

Definition at line 66 of file aiks_dl_runtime_effect_unittests.cc.

66 {
67 struct FragUniforms {
68 Size size;
69 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
70 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
71 uniform_data->resize(sizeof(FragUniforms));
72 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
73
74 DlPaint paint;
75 paint.setColorSource(
76 MakeRuntimeEffect(this, "gradient.frag.iplr", uniform_data));
77
78 DisplayListBuilder builder;
79 builder.Save();
80 builder.Scale(GetContentScale().x, GetContentScale().y);
81 builder.DrawPaint(paint);
82 builder.Restore();
83
84 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
85 }

References impeller::TSize< Scalar >::MakeWH(), and x.

## ◆ TEST_P() [167/494]

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(SkPoint{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() [168/494]

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() [169/494]

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

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

Definition at line 379 of file aiks_dl_text_unittests.cc.

379 {
380 DisplayListBuilder builder;
381
382 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
383 0.0, 1.0, 0.0, 0.0, //
384 0.0, 0.0, 1.0, 0.01, //
385 0.0, 0.0, 0.0, 1.0) * //
386 Matrix::MakeRotationY({Degrees{10}});
387
388 builder.Transform(SkM44::ColMajor(matrix.m));
389
390 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
391 "Roboto-Regular.ttf"));
392 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
393 }

References impeller::Matrix::m, RenderTextInCanvasSkia(), and impeller::Matrix::Transform().

## ◆ TEST_P() [171/494]

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

Definition at line 395 of file aiks_dl_text_unittests.cc.

395 {
396 DisplayListBuilder builder;
397
398 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
399 0.0, 1.0, 0.0, 0.0, //
400 0.0, 0.0, 1.0, 0.01, //
401 0.0, 0.0, 0.0, 1.0) * //
402 Matrix::MakeRotationY({Degrees{10}});
403
404 DlPaint save_paint;
405 SkRect window_bounds =
406 SkRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
407 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
408 builder.SaveLayer(&window_bounds, &save_paint);
409 builder.Transform(SkM44::ColMajor(matrix.m));
410
411 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
412 "Roboto-Regular.ttf"));
413
414 builder.Restore();
415 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
416 }

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

## ◆ TEST_P() [172/494]

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

Definition at line 270 of file aiks_dl_vertices_unittests.cc.

270 {
271 auto texture = CreateTextureForFixture("embarcadero.jpg");
272 auto dl_image = DlImageImpeller::Make(texture);
273 std::vector<DlPoint> positions = {
274 DlPoint(100, 300),
275 DlPoint(200, 100),
276 DlPoint(300, 300),
277 };
278 std::vector<DlPoint> texture_coordinates = {
279 DlPoint(0, 0),
280 DlPoint(100, 200),
281 DlPoint(200, 100),
282 };
283
284 auto vertices = flutter::DlVertices::Make(
285 flutter::DlVertexMode::kTriangles, 3, positions.data(),
286 texture_coordinates.data(), /*colors=*/nullptr);
287
288 flutter::DisplayListBuilder builder;
289 flutter::DlPaint paint;
290
291 auto image_source = flutter::DlColorSource::MakeImage(
292 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
293
294 paint.setColorSource(image_source);
295 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
296
297 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
298 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [173/494]

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

Definition at line 300 of file aiks_dl_vertices_unittests.cc.

301 {
302 auto texture = CreateTextureForFixture("embarcadero.jpg");
303 auto dl_image = DlImageImpeller::Make(texture);
304 std::vector<DlPoint> positions = {
305 DlPoint(100, 300),
306 DlPoint(200, 100),
307 DlPoint(300, 300),
308 };
309 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
310 flutter::DlColor::kGreen(),
311 flutter::DlColor::kWhite()};
312 std::vector<DlPoint> texture_coordinates = {
313 DlPoint(0, 0),
314 DlPoint(100, 200),
315 DlPoint(200, 100),
316 };
317
318 auto vertices = flutter::DlVertices::Make(
319 flutter::DlVertexMode::kTriangles, 3, positions.data(),
320 texture_coordinates.data(), colors.data());
321
322 flutter::DisplayListBuilder builder;
323 flutter::DlPaint paint;
324
325 auto image_source = flutter::DlColorSource::MakeImage(
326 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
327
328 paint.setColorSource(image_source);
329 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
330
331 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
332 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [174/494]

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

Definition at line 283 of file canvas_unittests.cc.

283 {
284 RenderCallback callback = [&](RenderTarget& render_target) {
285 ContentContext context(GetContext(), nullptr);
286 Canvas canvas(context, render_target, true, false);
287
288 std::vector<flutter::DlPoint> vertex_coordinates = {
289 flutter::DlPoint(0, 0),
290 flutter::DlPoint(600, 0),
291 flutter::DlPoint(0, 600),
292 };
293 std::vector<flutter::DlPoint> texture_coordinates = {
294 flutter::DlPoint(0, 0),
295 flutter::DlPoint(500, 0),
296 flutter::DlPoint(0, 500),
297 };
298 std::vector<uint16_t> indices = {0, 1, 2};
299 flutter::DlVertices::Builder vertices_builder(
300 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
301 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
302 vertices_builder.store_vertices(vertex_coordinates.data());
303 vertices_builder.store_indices(indices.data());
304 vertices_builder.store_texture_coordinates(texture_coordinates.data());
305 auto vertices = vertices_builder.build();
306
307 // The start and end points of the gradient form an empty rectangle.
308 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
309 flutter::DlColor::kRed()};
310 std::vector<Scalar> stops = {0.0, 1.0};
311 auto gradient = flutter::DlColorSource::MakeLinear(
312 {0, 0}, {0, 600}, 2, colors.data(), stops.data(),
313 flutter::DlTileMode::kClamp);
314
315 Paint paint;
316 paint.color_source = gradient.get();
317 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
318 BlendMode::kSourceOver, paint);
319
320 canvas.EndReplay();
321 return true;
322 };
323
324 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
325 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSourceOver, and impeller::Playground::OpenPlaygroundHere().

## ◆ TEST_P() [175/494]

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

Definition at line 209 of file aiks_dl_vertices_unittests.cc.

209 {
210 std::vector<DlPoint> positions = {
211 DlPoint(100, 300),
212 DlPoint(200, 100),
213 DlPoint(300, 300),
214 };
215
216 auto vertices = flutter::DlVertices::Make(
217 flutter::DlVertexMode::kTriangles, 3, positions.data(),
218 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
219
220 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
221 flutter::DlColor::kRed()};
222 const float stops[2] = {0.0, 1.0};
223
224 auto linear = flutter::DlColorSource::MakeLinear(
225 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
226 flutter::DlTileMode::kRepeat);
227
228 flutter::DisplayListBuilder builder;
229 flutter::DlPaint paint;
230
231 paint.setColorSource(linear);
232 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
233
234 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
235 }

## ◆ TEST_P() [176/494]

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

Definition at line 237 of file aiks_dl_vertices_unittests.cc.

237 {
238 std::vector<DlPoint> positions = {
239 DlPoint(100, 300),
240 DlPoint(200, 100),
241 DlPoint(300, 300),
242 };
243 std::vector<DlPoint> texture_coordinates = {
244 DlPoint(300, 100),
245 DlPoint(100, 200),
246 DlPoint(300, 300),
247 };
248
249 auto vertices = flutter::DlVertices::Make(
250 flutter::DlVertexMode::kTriangles, 3, positions.data(),
251 texture_coordinates.data(), /*colors=*/nullptr);
252
253 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
254 flutter::DlColor::kRed()};
255 const float stops[2] = {0.0, 1.0};
256
257 auto linear = flutter::DlColorSource::MakeLinear(
258 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
259 flutter::DlTileMode::kRepeat);
260
261 flutter::DisplayListBuilder builder;
262 flutter::DlPaint paint;
263
264 paint.setColorSource(linear);
265 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
266
267 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
268 }

## ◆ TEST_P() [177/494]

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

Definition at line 357 of file aiks_dl_vertices_unittests.cc.

357 {
358 std::vector<DlPoint> positions = {
359 DlPoint(100, 300),
360 DlPoint(200, 100),
361 DlPoint(300, 300),
362 DlPoint(200, 500),
363 };
364 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
365 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
366 std::vector<flutter::DlColor> colors = {color, color, color, color};
367
368 auto vertices = flutter::DlVertices::Make(
369 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
370 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
371 indices.data());
372
373 flutter::DisplayListBuilder builder;
374 flutter::DlPaint paint;
375 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
376 paint.setColor(flutter::DlColor::kRed());
377
378 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
379 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
380
381 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
382 }

## ◆ TEST_P() [178/494]

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

Definition at line 334 of file aiks_dl_vertices_unittests.cc.

334 {
335 std::vector<DlPoint> positions = {
336 DlPoint(100, 300),
337 DlPoint(200, 100),
338 DlPoint(300, 300),
339 DlPoint(200, 500),
340 };
341 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
342
343 auto vertices = flutter::DlVertices::Make(
344 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
345 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
346 indices.data());
347
348 flutter::DisplayListBuilder builder;
349 flutter::DlPaint paint;
350
351 paint.setColor(flutter::DlColor::kRed());
352 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
353
354 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
355 }

## ◆ TEST_P() [179/494]

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

Definition at line 183 of file aiks_dl_vertices_unittests.cc.

183 {
184 // Use negative coordinates and then scale the transform by -1, -1 to make
185 // sure coverage is taking the transform into account.
186 std::vector<DlPoint> positions = {
187 DlPoint(-100, -300),
188 DlPoint(-200, -100),
189 DlPoint(-300, -300),
190 };
191 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
192 flutter::DlColor::kGreen(),
193 flutter::DlColor::kWhite()};
194
195 auto vertices = flutter::DlVertices::Make(
196 flutter::DlVertexMode::kTriangles, 3, positions.data(),
197 /*texture_coordinates=*/nullptr, colors.data());
198
199 flutter::DisplayListBuilder builder;
200 flutter::DlPaint paint;
201
202 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
203 builder.Scale(-1, -1);
204 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
205
206 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
207 }

## ◆ TEST_P() [180/494]

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

Definition at line 416 of file aiks_dl_vertices_unittests.cc.

416 {
417 std::vector<DlPoint> positions_lt = {
418 DlPoint(0, 0), //
419 DlPoint(50, 0), //
420 DlPoint(0, 50), //
421 DlPoint(50, 50), //
422 };
423
424 auto vertices_lt = flutter::DlVertices::Make(
425 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
426 positions_lt.data(),
427 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
428 /*index_count=*/0,
429 /*indices=*/nullptr);
430
431 std::vector<DlPoint> positions_rt = {
432 DlPoint(50, 0), //
433 DlPoint(100, 0), //
434 DlPoint(50, 50), //
435 DlPoint(100, 50), //
436 };
437
438 auto vertices_rt = flutter::DlVertices::Make(
439 flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
440 positions_rt.data(),
441 /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
442 /*index_count=*/0,
443 /*indices=*/nullptr);
444
445 std::vector<DlPoint> positions_lb = {
446 DlPoint(0, 50), //
447 DlPoint(50, 50), //
448 DlPoint(0, 100), //
449 DlPoint(50, 100), //
450 };
451
452 auto vertices_lb = flutter::DlVertices::Make(
453 flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
454 positions_lb.data(),
455 /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
456 /*index_count=*/0,
457 /*indices=*/nullptr);
458
459 std::vector<DlPoint> positions_rb = {
460 DlPoint(50, 50), //
461 DlPoint(100, 50), //
462 DlPoint(50, 100), //
463 DlPoint(100, 100), //
464 };
465
466 auto vertices_rb = flutter::DlVertices::Make(
467 flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
468 positions_rb.data(),
469 /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
470 /*index_count=*/0,
471 /*indices=*/nullptr);
472
473 flutter::DisplayListBuilder builder;
474 flutter::DlPaint paint;
475 flutter::DlPaint rect_paint;
476 rect_paint.setColor(DlColor::kBlue());
477
478 auto runtime_stages =
479 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
480
481 auto runtime_stage =
482 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
483 ASSERT_TRUE(runtime_stage);
484
485 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
486 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
487 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
488 runtime_effect, {}, uniform_data);
489
490 paint.setColorSource(color_source);
491
492 builder.Scale(GetContentScale().x, GetContentScale().y);
493 builder.Save();
494 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), rect_paint);
495 builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
496 builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
497 builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
498 builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
499 builder.Restore();
500
501 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
502 }

References impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [181/494]

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

Definition at line 506 of file aiks_dl_vertices_unittests.cc.

507 {
508 std::vector<DlPoint> positions_lt = {
509 DlPoint(200, 200), //
510 DlPoint(250, 200), //
511 DlPoint(200, 250), //
512 DlPoint(250, 250), //
513 };
514
515 auto vertices = flutter::DlVertices::Make(
516 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
517 positions_lt.data(),
518 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
519 /*index_count=*/0,
520 /*indices=*/nullptr);
521
522 flutter::DisplayListBuilder builder;
523 flutter::DlPaint paint;
524 flutter::DlPaint rect_paint;
525 rect_paint.setColor(DlColor::kBlue());
526
527 auto runtime_stages =
528 OpenAssetAsRuntimeStage("runtime_stage_position.frag.iplr");
529
530 auto runtime_stage =
531 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
532 ASSERT_TRUE(runtime_stage);
533
534 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
535 auto rect_data = std::vector<Rect>{Rect::MakeLTRB(200, 200, 250, 250)};
536
537 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
538 uniform_data->resize(rect_data.size() * sizeof(Rect));
539 memcpy(uniform_data->data(), rect_data.data(), uniform_data->size());
540
541 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
542 runtime_effect, {}, uniform_data);
543
544 paint.setColorSource(color_source);
545
546 builder.Scale(GetContentScale().x, GetContentScale().y);
547 builder.DrawRect(DlRect::MakeLTRB(200, 200, 250, 250), rect_paint);
548 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
549
550 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
551 }

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

## ◆ TEST_P() [182/494]

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

Definition at line 327 of file canvas_unittests.cc.

327 {
328 auto runtime_stages =
329 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
330
331 auto runtime_stage =
332 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
333 ASSERT_TRUE(runtime_stage);
334
335 auto runtime_effect = flutter::DlRuntimeEffect::MakeImpeller(runtime_stage);
336 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
337 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
338 runtime_effect, {}, uniform_data);
339
340 RenderCallback callback = [&](RenderTarget& render_target) {
341 ContentContext context(GetContext(), nullptr);
342 Canvas canvas(context, render_target, true, false);
343
344 std::vector<flutter::DlPoint> vertex_coordinates = {
345 flutter::DlPoint(100, 100),
346 flutter::DlPoint(300, 100),
347 flutter::DlPoint(100, 300),
348 };
349 // The bounding box of the texture coordinates is empty.
350 std::vector<flutter::DlPoint> texture_coordinates = {
351 flutter::DlPoint(0, 0),
352 flutter::DlPoint(0, 100),
353 flutter::DlPoint(0, 0),
354 };
355 std::vector<uint16_t> indices = {0, 1, 2};
356 flutter::DlVertices::Builder vertices_builder(
357 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
358 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
359 vertices_builder.store_vertices(vertex_coordinates.data());
360 vertices_builder.store_indices(indices.data());
361 vertices_builder.store_texture_coordinates(texture_coordinates.data());
362 auto vertices = vertices_builder.build();
363
364 Paint paint;
365 paint.color_source = color_source.get();
366 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
367 BlendMode::kSourceOver, paint);
368
369 canvas.EndReplay();
370 return true;
371 };
372
373 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
374 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSourceOver, impeller::Playground::OpenPlaygroundHere(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [183/494]

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

Definition at line 384 of file aiks_dl_vertices_unittests.cc.

384 {
385 std::vector<DlPoint> positions = {
386 DlPoint(100, 300),
387 DlPoint(200, 100),
388 DlPoint(300, 300),
389 DlPoint(200, 500),
390 };
391 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3, 99, 100, 101};
392
393 auto vertices = flutter::DlVertices::Make(
394 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
395 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
396 indices.data());
397
398 EXPECT_EQ(vertices->GetBounds(), DlRect::MakeLTRB(100, 100, 300, 500));
399
400 flutter::DisplayListBuilder builder;
401 flutter::DlPaint paint;
402 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
403 paint.setColor(flutter::DlColor::kRed());
404
405 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
406 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrc, paint);
407
408 AiksContext renderer(GetContext(), nullptr);
409 std::shared_ptr<Texture> image =
410 DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
411 EXPECT_TRUE(image);
412 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [184/494]

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

Definition at line 1054 of file aiks_dl_basic_unittests.cc.

1054 {
1055 DisplayListBuilder builder;
1056 builder.Scale(GetContentScale().x, GetContentScale().y);
1057
1058 DlPaint paint;
1059 paint.setColor(DlColor::kRed());
1060 builder.DrawPaint(paint);
1061 builder.ClipRect(SkRect::MakeXYWH(100, 100, 200, 200));
1062 paint.setColor(DlColor::kBlue());
1063 builder.SaveLayer(nullptr, &paint);
1064 builder.Restore();
1065
1066 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1067 }

References x.

## ◆ TEST_P() [185/494]

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

Definition at line 1069 of file aiks_dl_basic_unittests.cc.

1069 {
1070 DisplayListBuilder builder;
1071 builder.Scale(GetContentScale().x, GetContentScale().y);
1072 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1073 builder.DrawImage(image, SkPoint{10, 10}, {});
1074 builder.ClipRect(SkRect::MakeXYWH(100, 100, 200, 200));
1075
1076 DlPaint paint;
1077 paint.setBlendMode(DlBlendMode::kClear);
1078 builder.SaveLayer(nullptr, &paint);
1079 builder.Restore();
1080
1081 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1082 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [186/494]

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

Definition at line 1473 of file aiks_dl_basic_unittests.cc.

1473 {
1474 DisplayListBuilder builder;
1475
1476 builder.Scale(GetContentScale().x, GetContentScale().y);
1477 DlPaint paint;
1478 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1479
1480 DlPaint save_paint;
1481 save_paint.setColor(DlColor::kWhite());
1482 builder.DrawPaint(save_paint);
1483
1484 paint.setColor(DlColor::kBlue());
1485 for (int i = 0; i < 5; i++) {
1486 Scalar y = i * 125;
1487 Scalar y_radius = i * 15;
1488 for (int j = 0; j < 5; j++) {
1489 Scalar x = j * 125;
1490 Scalar x_radius = j * 15;
1491 builder.DrawRRect(
1492 SkRRect::MakeRectXY(SkRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f),
1493 x_radius, y_radius),
1494 paint);
1495 }
1496 }
1497
1498 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1499 }

References x.

## ◆ TEST_P() [187/494]

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

Definition at line 833 of file aiks_dl_gradient_unittests.cc.

833 {
834 DisplayListBuilder builder;
835 DlPaint paint;
836 builder.Translate(100.0f, 0);
837
838 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
839 DlColor::kGreen()};
840 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
841
842 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {300, 0}, stops.size(),
843 colors.data(), stops.data(),
844 DlTileMode::kClamp));
845
846 paint.setColor(DlColor::kWhite());
847 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
848 builder.Translate(400, 0);
849 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
850 paint);
851
852 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
853 }

## ◆ TEST_P() [188/494]

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

Definition at line 879 of file aiks_dl_gradient_unittests.cc.

879 {
880 DisplayListBuilder builder;
881 DlPaint paint;
882 builder.Translate(100.0f, 0);
883
884 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
885 DlColor::kGreen()};
886 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
887
888 paint.setColorSource(DlColorSource::MakeLinear({300, 0}, {0, 0}, stops.size(),
889 colors.data(), stops.data(),
890 DlTileMode::kClamp));
891
892 paint.setColor(DlColor::kWhite());
893 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
894 builder.Translate(400, 0);
895 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
896 paint);
897
898 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
899 }

## ◆ TEST_P() [189/494]

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

Definition at line 856 of file aiks_dl_gradient_unittests.cc.

856 {
857 DisplayListBuilder builder;
858 DlPaint paint;
859 builder.Translate(100.0f, 0);
860
861 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
862 DlColor::kGreen()};
863 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
864
865 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {0, 300}, stops.size(),
866 colors.data(), stops.data(),
867 DlTileMode::kClamp));
868
869 paint.setColor(DlColor::kWhite());
870 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
871 builder.Translate(400, 0);
872 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
873 paint);
874
875 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
876 }

## ◆ TEST_P() [190/494]

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

Definition at line 902 of file aiks_dl_gradient_unittests.cc.

902 {
903 DisplayListBuilder builder;
904 DlPaint paint;
905 builder.Translate(100.0f, 0);
906
907 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
908 DlColor::kGreen()};
909 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
910
911 paint.setColorSource(DlColorSource::MakeLinear({0, 300}, {0, 0}, stops.size(),
912 colors.data(), stops.data(),
913 DlTileMode::kClamp));
914
915 paint.setColor(DlColor::kWhite());
916 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
917 builder.Translate(400, 0);
918 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
919 paint);
920
921 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
922 }

## ◆ TEST_P() [191/494]

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

Definition at line 464 of file aiks_dl_path_unittests.cc.

464 {
465 DlScalar stroke_width = 300;
466 DlScalar aspect = 1.0;
467 DlScalar start_angle = 0;
468 DlScalar end_angle = 90;
469 auto callback = [&]() -> sk_sp<DisplayList> {
470 if (AiksTest::ImGuiBegin("Controls", nullptr,
471 ImGuiWindowFlags_AlwaysAutoResize)) {
472 ImGui::SliderFloat("Stroke Width", &stroke_width, 1, 300);
473 ImGui::SliderFloat("Aspect", &aspect, 0.5, 2.0);
474 ImGui::SliderFloat("Start Angle", &start_angle, 0, 360);
475 ImGui::SliderFloat("End Angle", &end_angle, 0, 360);
476 ImGui::End();
477 }
478
479 DisplayListBuilder builder;
480 DlPaint grey_paint;
481 grey_paint.setColor(DlColor(0xff111111));
482 builder.DrawPaint(grey_paint);
483
484 DlPaint white_paint;
485 white_paint.setColor(DlColor::kWhite());
486 white_paint.setStrokeWidth(stroke_width);
487 white_paint.setDrawStyle(DlDrawStyle::kStroke);
488 DlPaint red_paint;
489 red_paint.setColor(DlColor::kRed());
490
491 Rect rect = Rect::MakeXYWH(100, 100, 100, aspect * 100);
492 builder.DrawRect(rect, red_paint);
493 builder.DrawArc(rect, start_angle, end_angle,
494 /*useCenter=*/false, white_paint);
495 DlScalar frontier = rect.GetRight() + stroke_width / 2.0;
496 builder.DrawLine(Point(frontier, 0), Point(frontier, 150), red_paint);
497
498 return builder.Build();
499 };
500 ASSERT_TRUE(OpenPlaygroundHere(callback));
501 }

References impeller::TRect< T >::GetRight(), impeller::AiksPlayground::ImGuiBegin(), impeller::TRect< Scalar >::MakeXYWH(), and stroke_width.

## ◆ TEST_P() [192/494]

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

Definition at line 433 of file aiks_dl_basic_unittests.cc.

433 {
434 DisplayListBuilder builder;
435 builder.Scale(GetContentScale().x, GetContentScale().y);
436 DlPaint paint;
437 const int color_count = 3;
438 DlColor colors[color_count] = {
439 DlColor::kBlue(),
440 DlColor::kGreen(),
441 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
442 };
443
444 paint.setColor(DlColor::kWhite());
445 builder.DrawPaint(paint);
446
447 int c_index = 0;
448 int radius = 600;
449 while (radius > 0) {
450 paint.setColor(colors[(c_index++) % color_count]);
451 builder.DrawCircle(SkPoint{10, 10}, radius, paint);
452 if (radius > 30) {
453 radius -= 10;
454 } else {
455 radius -= 2;
456 }
457 }
458
459 DlColor gradient_colors[7] = {
460 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
461 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
462 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
463 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
464 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
465 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
466 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
467 };
468 DlScalar stops[7] = {
469 0.0,
470 (1.0 / 6.0) * 1,
471 (1.0 / 6.0) * 2,
472 (1.0 / 6.0) * 3,
473 (1.0 / 6.0) * 4,
474 (1.0 / 6.0) * 5,
475 1.0,
476 };
477 auto texture = CreateTextureForFixture("airplane.jpg",
478 /*enable_mipmapping=*/true);
479 auto image = DlImageImpeller::Make(texture);
480
481 paint.setColorSource(DlColorSource::MakeRadial(
482 {500, 600}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
483 builder.DrawCircle(SkPoint{500, 600}, 100, paint);
484
485 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
486 paint.setColorSource(DlColorSource::MakeImage(
487 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
488 DlImageSampling::kNearestNeighbor, &local_matrix));
489 builder.DrawCircle(SkPoint{800, 300}, 100, paint);
490
491 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
492 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [193/494]

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

Definition at line 560 of file aiks_dl_basic_unittests.cc.

560 {
561 DisplayListBuilder builder;
562 builder.Scale(GetContentScale().x, GetContentScale().y);
563 DlPaint paint;
564 const int color_count = 3;
565 DlColor colors[color_count] = {
566 DlColor::kBlue(),
567 DlColor::kGreen(),
568 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
569 };
570
571 paint.setColor(DlColor::kWhite());
572 builder.DrawPaint(paint);
573
574 int c_index = 0;
575 int long_radius = 600;
576 int short_radius = 600;
577 while (long_radius > 0 && short_radius > 0) {
578 paint.setColor(colors[(c_index++) % color_count]);
579 builder.DrawOval(SkRect::MakeXYWH(10 - long_radius, 10 - short_radius,
580 long_radius * 2, short_radius * 2),
581 paint);
582 builder.DrawOval(SkRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
583 short_radius * 2, long_radius * 2),
584 paint);
585 if (short_radius > 30) {
586 short_radius -= 10;
587 long_radius -= 5;
588 } else {
589 short_radius -= 2;
590 long_radius -= 1;
591 }
592 }
593
594 DlColor gradient_colors[7] = {
595 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
596 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
597 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
598 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
599 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
600 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
601 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
602 };
603 DlScalar stops[7] = {
604 0.0,
605 (1.0 / 6.0) * 1,
606 (1.0 / 6.0) * 2,
607 (1.0 / 6.0) * 3,
608 (1.0 / 6.0) * 4,
609 (1.0 / 6.0) * 5,
610 1.0,
611 };
612 auto texture = CreateTextureForFixture("airplane.jpg",
613 /*enable_mipmapping=*/true);
614 auto image = DlImageImpeller::Make(texture);
615
616 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
617
618 paint.setColorSource(DlColorSource::MakeRadial(
619 {300, 650}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
620 builder.DrawOval(SkRect::MakeXYWH(200, 625, 200, 50), paint);
621 builder.DrawOval(SkRect::MakeXYWH(275, 550, 50, 200), paint);
622
623 DlMatrix local_matrix = DlMatrix::MakeTranslation({610, 15});
624 paint.setColorSource(DlColorSource::MakeImage(
625 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
626 DlImageSampling::kNearestNeighbor, &local_matrix));
627 builder.DrawOval(SkRect::MakeXYWH(610, 90, 200, 50), paint);
628 builder.DrawOval(SkRect::MakeXYWH(685, 15, 50, 200), paint);
629
630 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
631 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [194/494]

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

Definition at line 1205 of file aiks_dl_basic_unittests.cc.

1205 {
1206 DisplayListBuilder builder;
1207 builder.Scale(GetContentScale().x, GetContentScale().y);
1208
1209 DlPaint paint;
1210 const int color_count = 3;
1211 DlColor colors[color_count] = {
1212 DlColor::kBlue(),
1213 DlColor::kGreen(),
1214 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1215 };
1216
1217 paint.setColor(DlColor::kWhite());
1218 builder.DrawPaint(paint);
1219
1220 auto draw_rrect_as_path = [&builder](const SkRect& rect, Scalar x, Scalar y,
1221 const DlPaint& paint) {
1222 SkPath path;
1223 path.addRoundRect(rect, x, y);
1224 builder.DrawPath(path, paint);
1225 };
1226
1227 int c_index = 0;
1228 for (int i = 0; i < 4; i++) {
1229 for (int j = 0; j < 4; j++) {
1230 paint.setColor(colors[(c_index++) % color_count]);
1231 draw_rrect_as_path(SkRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1232 i * 5 + 10, j * 5 + 10, paint);
1233 }
1234 }
1235 paint.setColor(colors[(c_index++) % color_count]);
1236 draw_rrect_as_path(SkRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1237 paint.setColor(colors[(c_index++) % color_count]);
1238 draw_rrect_as_path(SkRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1239
1240 std::vector<DlColor> gradient_colors = {
1241 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1242 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1243 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1244 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1245 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1246 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1247 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1248 std::vector<Scalar> stops = {
1249 0.0,
1250 (1.0 / 6.0) * 1,
1251 (1.0 / 6.0) * 2,
1252 (1.0 / 6.0) * 3,
1253 (1.0 / 6.0) * 4,
1254 (1.0 / 6.0) * 5,
1255 1.0,
1256 };
1257 auto texture = DlImageImpeller::Make(
1258 CreateTextureForFixture("airplane.jpg",
1259 /*enable_mipmapping=*/true));
1260
1261 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1262 paint.setColorSource(DlColorSource::MakeRadial(
1263 /*center=*/{550, 550},
1264 /*radius=*/75,
1265 /*stop_count=*/gradient_colors.size(),
1266 /*colors=*/gradient_colors.data(),
1267 /*stops=*/stops.data(),
1268 /*tile_mode=*/DlTileMode::kMirror));
1269 for (int i = 1; i <= 10; i++) {
1270 int j = 11 - i;
1271 draw_rrect_as_path(SkRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1272 550 + i * 20, 550 + j * 20),
1273 i * 10, j * 10, paint);
1274 }
1275 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1276 paint.setColorSource(DlColorSource::MakeRadial(
1277 /*center=*/{200, 650},
1278 /*radius=*/75,
1279 /*stop_count=*/gradient_colors.size(),
1280 /*colors=*/gradient_colors.data(),
1281 /*stops=*/stops.data(),
1282 /*tile_mode=*/DlTileMode::kMirror));
1283 draw_rrect_as_path(SkRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1284 draw_rrect_as_path(SkRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1285
1286 auto matrix = DlMatrix::MakeTranslation({520, 20});
1287 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1288 paint.setColorSource(DlColorSource::MakeImage(
1289 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1290 DlImageSampling::kMipmapLinear, &matrix));
1291 for (int i = 1; i <= 10; i++) {
1292 int j = 11 - i;
1293 draw_rrect_as_path(SkRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1294 720 + i * 20, 220 + j * 20),
1295 i * 10, j * 10, paint);
1296 }
1297 matrix = DlMatrix::MakeTranslation({800, 300});
1298 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1299 paint.setColorSource(DlColorSource::MakeImage(
1300 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1301 DlImageSampling::kMipmapLinear, &matrix));
1302
1303 draw_rrect_as_path(SkRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1304 draw_rrect_as_path(SkRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1305
1306 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1307 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [195/494]

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

Definition at line 633 of file aiks_dl_basic_unittests.cc.

633 {
634 DisplayListBuilder builder;
635 builder.Scale(GetContentScale().x, GetContentScale().y);
636 DlPaint paint;
637 const int color_count = 3;
638 DlColor colors[color_count] = {
639 DlColor::kBlue(),
640 DlColor::kGreen(),
641 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
642 };
643
644 paint.setColor(DlColor::kWhite());
645 builder.DrawPaint(paint);
646
647 int c_index = 0;
648 for (int i = 0; i < 4; i++) {
649 for (int j = 0; j < 4; j++) {
650 paint.setColor(colors[(c_index++) % color_count]);
651 builder.DrawRRect(
652 SkRRect::MakeRectXY(
653 SkRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
654 i * 5 + 10, j * 5 + 10),
655 paint);
656 }
657 }
658 paint.setColor(colors[(c_index++) % color_count]);
659 builder.DrawRRect(
660 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 420, 380, 80), 40, 40), paint);
661 paint.setColor(colors[(c_index++) % color_count]);
662 builder.DrawRRect(
663 SkRRect::MakeRectXY(SkRect::MakeXYWH(410, 20, 80, 380), 40, 40), paint);
664
665 DlColor gradient_colors[7] = {
666 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
667 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
668 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
669 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
670 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
671 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
672 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
673 };
674 DlScalar stops[7] = {
675 0.0,
676 (1.0 / 6.0) * 1,
677 (1.0 / 6.0) * 2,
678 (1.0 / 6.0) * 3,
679 (1.0 / 6.0) * 4,
680 (1.0 / 6.0) * 5,
681 1.0,
682 };
683 auto texture = CreateTextureForFixture("airplane.jpg",
684 /*enable_mipmapping=*/true);
685 auto image = DlImageImpeller::Make(texture);
686
687 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
688 paint.setColorSource(DlColorSource::MakeRadial(
689 {550, 550}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
690 for (int i = 1; i <= 10; i++) {
691 int j = 11 - i;
692 builder.DrawRRect(
693 SkRRect::MakeRectXY(SkRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
694 550 + i * 20, 550 + j * 20),
695 i * 10, j * 10),
696 paint);
697 }
698
699 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
700 paint.setColorSource(DlColorSource::MakeRadial(
701 {200, 650}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
702 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
703 builder.DrawRRect(
704 SkRRect::MakeRectXY(SkRect::MakeLTRB(100, 610, 300, 690), 40, 40), paint);
705 builder.DrawRRect(
706 SkRRect::MakeRectXY(SkRect::MakeLTRB(160, 550, 240, 750), 40, 40), paint);
707
708 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
709 DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
710 paint.setColorSource(DlColorSource::MakeImage(
711 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
712 DlImageSampling::kNearestNeighbor, &local_matrix));
713 for (int i = 1; i <= 10; i++) {
714 int j = 11 - i;
715 builder.DrawRRect(
716 SkRRect::MakeRectXY(SkRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
717 720 + i * 20, 220 + j * 20),
718 i * 10, j * 10),
719 paint);
720 }
721
722 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
723 local_matrix = DlMatrix::MakeTranslation({800, 300});
724 paint.setColorSource(DlColorSource::MakeImage(
725 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
726 DlImageSampling::kNearestNeighbor, &local_matrix));
727 builder.DrawRRect(
728 SkRRect::MakeRectXY(SkRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
729 paint);
730 builder.DrawRRect(
731 SkRRect::MakeRectXY(SkRect::MakeLTRB(860, 350, 940, 550), 40, 40), paint);
732
733 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
734 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [196/494]

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

Definition at line 734 of file aiks_dl_blend_unittests.cc.

734 {
735 auto texture = CreateTextureForFixture("airplane.jpg",
736 /*enable_mipmapping=*/true);
737
738 DisplayListBuilder builder;
739 builder.Rotate(30);
740
741 DlPaint image_paint;
742 image_paint.setColorFilter(DlColorFilter::MakeBlend(
743 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
744 DlBlendMode::kColorDodge));
745
746 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint{200, 200},
747 DlImageSampling::kMipmapLinear, &image_paint);
748
749 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
750 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [197/494]

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

Definition at line 469 of file aiks_dl_blend_unittests.cc.

469 {
470 DisplayListBuilder builder;
471
472 DlPaint save_paint;
473 save_paint.setColorFilter(
474 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kColorDodge));
475 builder.SaveLayer(nullptr, &save_paint);
476
477 builder.Translate(500, 300);
478 builder.Rotate(120);
479
480 DlPaint paint;
481 paint.setColor(DlColor::kBlue());
482 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), paint);
483
484 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
485 }

## ◆ TEST_P() [198/494]

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

Definition at line 716 of file aiks_dl_blend_unittests.cc.

716 {
717 auto texture = CreateTextureForFixture("airplane.jpg",
718 /*enable_mipmapping=*/true);
719
720 DisplayListBuilder builder;
721 builder.Rotate(30);
722
723 DlPaint image_paint;
724 image_paint.setColorFilter(DlColorFilter::MakeBlend(
725 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
726 DlBlendMode::kSrcIn));
727
728 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint{200, 200},
729 DlImageSampling::kMipmapLinear, &image_paint);
730
731 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
732 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [199/494]

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

Definition at line 1118 of file aiks_dl_basic_unittests.cc.

1118 {
1119 PixelFormat pixel_format =
1120 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1121 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1122 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1123 << "pixel format: " << PixelFormatToString(pixel_format);
1124 }

References impeller::kB8G8R8A8UNormInt, impeller::kR8G8B8A8UNormInt, and impeller::PixelFormatToString().

## ◆ TEST_P() [200/494]

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

Definition at line 1113 of file aiks_dl_basic_unittests.cc.

1113 {
1114 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1115 PixelFormat::kB10G10R10A10XR);
1116 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [201/494]

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

Definition at line 752 of file aiks_dl_blend_unittests.cc.

752 {
753 auto texture = CreateTextureForFixture("airplane.jpg",
754 /*enable_mipmapping=*/true);
755
756 // Draw with an advanced blend that can use FramebufferBlendContents and
757 // verify that the scale transform is correctly applied to the image.
758 DisplayListBuilder builder;
759
760 DlPaint paint;
761 paint.setColor(
762 DlColor::RGBA(169.0f / 255.0f, 169.0f / 255.0f, 169.0f / 255.0f, 1.0f));
763 builder.DrawPaint(paint);
764 builder.Scale(0.4, 0.4);
765
766 DlPaint image_paint;
767 image_paint.setBlendMode(DlBlendMode::kMultiply);
768
769 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint{20, 20},
770 DlImageSampling::kMipmapLinear, &image_paint);
771
772 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
773 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [202/494]

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

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

Definition at line 852 of file aiks_dl_blur_unittests.cc.

852 {
853 // This test is for checking out how stable rendering is when content is
854 // translated underneath a blur. Animating under a blur can cause
855 // *shimmering* to happen as a result of pixel alignment.
856 // See also: https://github.com/flutter/flutter/issues/140193
857 auto boston =
858 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
859 ASSERT_TRUE(boston);
860 int64_t count = 0;
861 Scalar sigma = 20.0;
862 Scalar freq = 0.1;
863 Scalar amp = 50.0;
864 auto callback = [&]() -> sk_sp<DisplayList> {
865 if (AiksTest::ImGuiBegin("Controls", nullptr,
866 ImGuiWindowFlags_AlwaysAutoResize)) {
867 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
868 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
869 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
870 ImGui::End();
871 }
872
873 DisplayListBuilder builder;
874 builder.Scale(GetContentScale().x, GetContentScale().y);
875 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
876 builder.DrawImage(
877 DlImageImpeller::Make(boston),
878 SkPoint::Make(1024 / 2 - boston->GetSize().width / 2,
879 (768 / 2 - boston->GetSize().height / 2) + y),
880 DlImageSampling::kMipmapLinear);
881 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
882 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
883 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
884
885 builder.ClipRect(
886 SkRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
887 builder.ClipRect(SkRect::MakeLTRB(100, 100, 900, 700));
888
889 DlPaint paint;
890 paint.setBlendMode(DlBlendMode::kSrc);
891
892 auto backdrop_filter =
893 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
894 builder.SaveLayer(nullptr, &paint, backdrop_filter.get());
895 count += 1;
896 return builder.Build();
897 };
898 ASSERT_TRUE(OpenPlaygroundHere(callback));
899 }

References impeller::DrawPlaygroundLine(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), and x.

## ◆ TEST_P() [204/494]

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

Definition at line 823 of file aiks_dl_blur_unittests.cc.

823 {
824 DisplayListBuilder builder;
825
826 builder.Scale(GetContentScale().x, GetContentScale().y);
827 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
828 builder.DrawImageRect(
829 DlImageImpeller::Make(boston),
830 SkRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
831 SkRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
832 DlImageSampling::kNearestNeighbor);
833
834 DlPaint paint;
835 paint.setColor(DlColor::kMagenta());
836
837 SkRRect rrect = SkRRect::MakeRectXY(
838 SkRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
839 builder.DrawRRect(rrect, paint);
840 builder.ClipRect(SkRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
841
842 DlPaint save_paint;
843 save_paint.setBlendMode(DlBlendMode::kSrc);
844
845 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
846 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
847
848 builder.Restore();
849 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
850 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [205/494]

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

Definition at line 795 of file aiks_dl_blur_unittests.cc.

795 {
796 DisplayListBuilder builder;
797
798 DlPaint paint;
799 builder.Scale(GetContentScale().x, GetContentScale().y);
800
801 paint.setColor(DlColor::kLimeGreen());
802 SkRRect rrect = SkRRect::MakeRectXY(
803 SkRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
804 builder.DrawRRect(rrect, paint);
805
806 paint.setColor(DlColor::kMagenta());
807 rrect = SkRRect::MakeRectXY(
808 SkRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
809 builder.DrawRRect(rrect, paint);
810 builder.ClipRect(SkRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
811
812 DlPaint save_paint;
813 save_paint.setBlendMode(DlBlendMode::kSrc);
814
815 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
816
817 builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
818 builder.Restore();
819
820 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
821 }

References x.

## ◆ TEST_P() [206/494]

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

Definition at line 1342 of file aiks_dl_blur_unittests.cc.

1342 {
1343 AiksContext renderer(GetContext(), nullptr);
1344 for (int32_t i = 1; i < 5; ++i) {
1345 DisplayListBuilder builder;
1346
1347 ISize clip_size = ISize(i, i);
1348 builder.Save();
1349 builder.ClipRect(
1350 SkRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1351
1352 DlPaint paint;
1353 paint.setColor(DlColor::kGreen());
1354 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kDecal);
1355 paint.setImageFilter(blur_filter);
1356
1357 builder.DrawCircle(SkPoint{400, 400}, 200, paint);
1358 builder.Restore();
1359
1360 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1361 EXPECT_TRUE(image) << " length " << i;
1362 }
1363 }

References impeller::DisplayListToTexture(), impeller::TSize< T >::height, and impeller::TSize< T >::width.

## ◆ TEST_P() [207/494]

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

Definition at line 1099 of file aiks_dl_blur_unittests.cc.

1099 {
1100 DisplayListBuilder builder;
1101
1102 builder.Scale(GetContentScale().x, GetContentScale().y);
1103 builder.Scale(0.5, 0.5);
1104
1105 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1106 builder.DrawImage(DlImageImpeller::Make(boston), SkPoint{100, 100}, {});
1107
1108 DlPaint paint;
1109 paint.setBlendMode(DlBlendMode::kSrc);
1110
1111 auto backdrop_filter = DlImageFilter::MakeBlur(50, 0, DlTileMode::kClamp);
1112 builder.SaveLayer(nullptr, &paint, backdrop_filter.get());
1113 builder.Restore();
1114 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1115 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [208/494]

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

Definition at line 1121 of file aiks_dl_blur_unittests.cc.

1121 {
1122 DisplayListBuilder builder;
1123
1124 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1125 Rect bounds =
1126 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1127
1128 DlPaint paint;
1129 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1130
1131 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1132 Vector2 clip_size = {150, 75};
1133 Vector2 center = Vector2(1024, 768) / 2;
1134 builder.Scale(GetContentScale().x, GetContentScale().y);
1135
1136 auto clip_bounds =
1137 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1138 builder.ClipRect(SkRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1139 clip_bounds.GetRight(),
1140 clip_bounds.GetBottom()));
1141 builder.Translate(center.x, center.y);
1142 builder.Scale(0.6, 0.6);
1143 builder.Rotate(25);
1144
1145 auto dst_rect = bounds.Shift(-image_center);
1146 builder.DrawImageRect(
1147 DlImageImpeller::Make(boston), /*src=*/
1148 SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1149 bounds.GetBottom()),
1150 /*dst=*/
1151 SkRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1152 dst_rect.GetRight(), dst_rect.GetBottom()),
1153 DlImageSampling::kMipmapLinear, &paint);
1154
1155 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1156 }

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

## ◆ TEST_P() [209/494]

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

Definition at line 1044 of file aiks_dl_blur_unittests.cc.

1044 {
1045 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1046
1047 auto callback = [&]() -> sk_sp<DisplayList> {
1048 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1049 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1050 DlTileMode::kMirror, DlTileMode::kDecal};
1051
1052 static float rotation = 0;
1053 static float scale = 0.6;
1054 static int selected_tile_mode = 3;
1055
1056 if (AiksTest::ImGuiBegin("Controls", nullptr,
1057 ImGuiWindowFlags_AlwaysAutoResize)) {
1058 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1059 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1060 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1061 sizeof(tile_mode_names) / sizeof(char*));
1062 ImGui::End();
1063 }
1064
1065 DisplayListBuilder builder;
1066 Rect bounds =
1067 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1068 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1069 DlPaint paint;
1070 paint.setImageFilter(
1071 DlImageFilter::MakeBlur(20, 20, tile_modes[selected_tile_mode]));
1072
1073 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
1074 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
1075 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
1076 Vector2 center = Vector2(1024, 768) / 2;
1077
1078 builder.Scale(GetContentScale().x, GetContentScale().y);
1079 builder.ClipRect(
1080 SkRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
1081 builder.Translate(center.x, center.y);
1082 builder.Scale(scale, scale);
1083 builder.Rotate(rotation);
1084
1085 SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1086 bounds.GetRight(), bounds.GetBottom());
1087 Rect dest = bounds.Shift(-image_center);
1088 SkRect sk_dst = SkRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1089 dest.GetRight(), dest.GetBottom());
1090 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1091 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1092 &paint);
1093 return builder.Build();
1094 };
1095
1096 ASSERT_TRUE(OpenPlaygroundHere(callback));
1097 }

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

## ◆ TEST_P() [210/494]

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

Definition at line 1158 of file aiks_dl_blur_unittests.cc.

1158 {
1159 auto callback = [&]() -> sk_sp<DisplayList> {
1160 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1161 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1162 DlTileMode::kMirror, DlTileMode::kDecal};
1163
1164 static float rotation = 45;
1165 static float scale = 0.6;
1166 static int selected_tile_mode = 3;
1167
1168 if (AiksTest::ImGuiBegin("Controls", nullptr,
1169 ImGuiWindowFlags_AlwaysAutoResize)) {
1170 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1171 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1172 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1173 sizeof(tile_mode_names) / sizeof(char*));
1174 ImGui::End();
1175 }
1176
1177 DisplayListBuilder builder;
1178
1179 DlPaint paint;
1180 paint.setColor(DlColor::kGreen());
1181 paint.setImageFilter(
1182 DlImageFilter::MakeBlur(50, 0, tile_modes[selected_tile_mode]));
1183
1184 Vector2 center = Vector2(1024, 768) / 2;
1185 builder.Scale(GetContentScale().x, GetContentScale().y);
1186 builder.Translate(center.x, center.y);
1187 builder.Scale(scale, scale);
1188 builder.Rotate(rotation);
1189
1190 SkRRect rrect =
1191 SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
1192 builder.DrawRRect(rrect, paint);
1193 return builder.Build();
1194 };
1195
1196 ASSERT_TRUE(OpenPlaygroundHere(callback));
1197 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::TPoint< T >::Rotate(), scale, impeller::TPoint< T >::x, x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [211/494]

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

Definition at line 1011 of file aiks_dl_blur_unittests.cc.

1011 {
1012 DisplayListBuilder builder;
1013 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1014 Rect bounds =
1015 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1016 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1017
1018 DlPaint paint;
1019 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1020
1021 Vector2 clip_size = {150, 75};
1022 Vector2 center = Vector2(1024, 768) / 2;
1023 builder.Scale(GetContentScale().x, GetContentScale().y);
1024
1025 auto rect =
1026 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1027 builder.ClipRect(SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
1028 rect.GetRight(), rect.GetBottom()));
1029 builder.Translate(center.x, center.y);
1030 builder.Scale(0.6, 0.6);
1031
1032 SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1033 bounds.GetRight(), bounds.GetBottom());
1034 Rect dest = bounds.Shift(-image_center);
1035 SkRect sk_dst = SkRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1036 dest.GetRight(), dest.GetBottom());
1037 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1038 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1039 &paint);
1040
1041 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1042 }

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

## ◆ TEST_P() [212/494]

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

Definition at line 1317 of file aiks_dl_blur_unittests.cc.

1317 {
1318 AiksContext renderer(GetContext(), nullptr);
1319
1320 for (int32_t i = 1; i < 5; ++i) {
1321 DisplayListBuilder builder;
1322 Scalar fi = i;
1323 SkPath path;
1324 path.moveTo(100, 100);
1325 path.lineTo(100 + fi, 100 + fi);
1326
1327 DlPaint paint;
1328 paint.setColor(DlColor::kChartreuse());
1329 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kClamp);
1330 paint.setImageFilter(blur_filter);
1331
1332 builder.DrawPath(path, paint);
1333
1334 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1335 EXPECT_TRUE(image) << " length " << i;
1336 }
1337 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [213/494]

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

Definition at line 650 of file aiks_dl_blur_unittests.cc.

650 {
651 DisplayListBuilder builder;
652 builder.Scale(GetContentScale().x, GetContentScale().y);
653
654 DlPaint paint;
655 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
656 builder.DrawPaint(paint);
657
658 paint.setColor(DlColor::kGreen());
659 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
660
661 SkPath path;
662 path.moveTo(200, 200);
663 path.lineTo(300, 400);
664 path.lineTo(100, 400);
665 path.close();
666
667 builder.DrawPath(path, paint);
668
669 // Draw another thing to make sure the clip area is reset.
670 DlPaint red;
671 red.setColor(DlColor::kRed());
672 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
673
674 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
675 }

References x.

## ◆ TEST_P() [214/494]

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

Definition at line 901 of file aiks_dl_blur_unittests.cc.

901 {
902 DisplayListBuilder builder;
903
904 builder.Scale(GetContentScale().x, GetContentScale().y);
905
906 DlPaint paint;
907 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
908 builder.DrawPaint(paint);
909
910 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
911 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
912 std::vector<Scalar> stops = {0.0, 1.0};
913
914 paint = DlPaint{};
915 paint.setColorSource(DlColorSource::MakeLinear(
916 /*start_point=*/{0, 0},
917 /*end_point=*/{200, 200},
918 /*stop_count=*/colors.size(),
919 /*colors=*/colors.data(),
920 /*stops=*/stops.data(),
921 /*tile_mode=*/DlTileMode::kMirror));
922 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
923
924 SkPath path;
925 path.moveTo(200, 200);
926 path.lineTo(300, 400);
927 path.lineTo(100, 400);
928 path.close();
929 builder.DrawPath(path, paint);
930
931 // Draw another thing to make sure the clip area is reset.
932 DlPaint red;
933 red.setColor(DlColor::kRed());
934 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
935
936 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
937 }

References x.

## ◆ TEST_P() [215/494]

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

Definition at line 677 of file aiks_dl_blur_unittests.cc.

677 {
678 DisplayListBuilder builder;
679 builder.Scale(GetContentScale().x, GetContentScale().y);
680
681 DlPaint paint;
682 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
683 builder.DrawPaint(paint);
684
685 paint.setColor(DlColor::kGreen());
686 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
687
688 SkPath path;
689 path.moveTo(200, 200);
690 path.lineTo(300, 400);
691 path.lineTo(100, 400);
692 path.close();
693
694 builder.DrawPath(path, paint);
695
696 // Draw another thing to make sure the clip area is reset.
697 DlPaint red;
698 red.setColor(DlColor::kRed());
699 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
700
701 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
702 }

References x.

## ◆ TEST_P() [216/494]

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

Definition at line 975 of file aiks_dl_blur_unittests.cc.

975 {
976 DisplayListBuilder builder;
977 builder.Scale(GetContentScale().x, GetContentScale().y);
978
979 DlPaint paint;
980 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
981 builder.DrawPaint(paint);
982
983 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
984 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
985 std::vector<Scalar> stops = {0.0, 1.0};
986
987 paint = DlPaint{};
988 paint.setColorSource(DlColorSource::MakeLinear(
989 /*start_point=*/{0, 0},
990 /*end_point=*/{200, 200},
991 /*stop_count=*/colors.size(),
992 /*colors=*/colors.data(),
993 /*stops=*/stops.data(),
994 /*tile_mode=*/DlTileMode::kMirror));
995 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
996
997 SkPath path;
998 path.moveTo(200, 200);
999 path.lineTo(300, 400);
1000 path.lineTo(100, 400);
1001 path.close();
1002 builder.DrawPath(path, paint);
1003
1004 // Draw another thing to make sure the clip area is reset.
1005 DlPaint red;
1006 red.setColor(DlColor::kRed());
1007 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
1008 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1009 }

References x.

## ◆ TEST_P() [217/494]

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

Definition at line 704 of file aiks_dl_blur_unittests.cc.

704 {
705 DisplayListBuilder builder;
706 builder.Scale(GetContentScale().x, GetContentScale().y);
707
708 DlPaint paint;
709 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
710 builder.DrawPaint(paint);
711
712 paint.setColor(DlColor::kGreen());
713 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
714
715 SkPath path;
716 path.moveTo(200, 200);
717 path.lineTo(300, 400);
718 path.lineTo(100, 400);
719 path.close();
720
721 builder.DrawPath(path, paint);
722
723 // Draw another thing to make sure the clip area is reset.
724 DlPaint red;
725 red.setColor(DlColor::kRed());
726 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
727
728 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
729 }

References x.

## ◆ TEST_P() [218/494]

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

Definition at line 939 of file aiks_dl_blur_unittests.cc.

939 {
940 DisplayListBuilder builder;
941 builder.Scale(GetContentScale().x, GetContentScale().y);
942
943 DlPaint paint;
944 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
945 builder.DrawPaint(paint);
946
947 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
948 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
949 std::vector<Scalar> stops = {0.0, 1.0};
950
951 paint = DlPaint{};
952 paint.setColorSource(DlColorSource::MakeLinear(
953 /*start_point=*/{0, 0},
954 /*end_point=*/{200, 200},
955 /*stop_count=*/colors.size(),
956 /*colors=*/colors.data(),
957 /*stops=*/stops.data(),
958 /*tile_mode=*/DlTileMode::kMirror));
959 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
960
961 SkPath path;
962 path.moveTo(200, 200);
963 path.lineTo(300, 400);
964 path.lineTo(100, 400);
965 path.close();
966 builder.DrawPath(path, paint);
967
968 // Draw another thing to make sure the clip area is reset.
969 DlPaint red;
970 red.setColor(DlColor::kRed());
971 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
972 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
973 }

References x.

## ◆ TEST_P() [219/494]

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

Definition at line 1263 of file aiks_dl_blur_unittests.cc.

1263 {
1264 if (GetParam() != PlaygroundBackend::kMetal) {
1265 GTEST_SKIP()
1266 << "This backend doesn't yet support setting device capabilities.";
1267 }
1268 if (!WillRenderSomething()) {
1269 // Sometimes these tests are run without playgrounds enabled which is
1270 // pointless for this test since we are asserting that
1271 // `SupportsDecalSamplerAddressMode` is called.
1272 GTEST_SKIP() << "This test requires playgrounds.";
1273 }
1274
1275 std::shared_ptr<const Capabilities> old_capabilities =
1276 GetContext()->GetCapabilities();
1277 auto mock_capabilities = std::make_shared<MockCapabilities>();
1278 EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode())
1279 .Times(::testing::AtLeast(1))
1280 .WillRepeatedly(::testing::Return(false));
1281 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
1282 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
1283 FLT_FORWARD(mock_capabilities, old_capabilities,
1284 GetDefaultDepthStencilFormat);
1285 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
1286 FLT_FORWARD(mock_capabilities, old_capabilities,
1287 SupportsImplicitResolvingMSAA);
1288 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
1289 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch);
1290 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
1291 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
1292 FLT_FORWARD(mock_capabilities, old_capabilities,
1293 SupportsTextureToTextureBlits);
1294 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
1295 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTriangleFan);
1296 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsPrimitiveRestart);
1297 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
1298
1299 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
1300
1301 DisplayListBuilder builder;
1302 builder.Scale(GetContentScale().x * 0.5, GetContentScale().y * 0.5);
1303
1304 DlPaint paint;
1305 paint.setColor(DlColor::kBlack());
1306 builder.DrawPaint(paint);
1307
1308 auto blur_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal);
1309 paint.setImageFilter(blur_filter);
1310 builder.DrawImage(texture, SkPoint::Make(200, 200), {}, &paint);
1311 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1312 }

References impeller::kMetal, impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [220/494]

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() [221/494]

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() [222/494]

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() [223/494]

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() [224/494]

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() [225/494]

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

Definition at line 741 of file aiks_dl_gradient_unittests.cc.

741 {
742 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
743 auto callback = [&]() -> sk_sp<DisplayList> {
744 static float scale = 3;
745 static bool add_circle_clip = true;
746 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
747 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
748 DlTileMode::kMirror, DlTileMode::kDecal};
749 static int selected_tile_mode = 0;
750 static float alpha = 1;
751
752 if (AiksTest::ImGuiBegin("Controls", nullptr,
753 ImGuiWindowFlags_AlwaysAutoResize)) {
754 ImGui::SliderFloat("Scale", &scale, 0, 6);
755 ImGui::Checkbox("Circle clip", &add_circle_clip);
756 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
757 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
758 sizeof(tile_mode_names) / sizeof(char*));
759 ImGui::End();
760 }
761
762 DisplayListBuilder builder;
763 builder.Scale(GetContentScale().x, GetContentScale().y);
764 DlPaint paint;
765 paint.setColor(DlColor::kWhite());
766 builder.DrawPaint(paint);
767
768 paint.setDrawStyle(DlDrawStyle::kStroke);
769 paint.setColor(DlColor::kWhite().withAlpha(alpha * 255));
770 paint.setStrokeWidth(10);
771 auto tile_mode = tile_modes[selected_tile_mode];
772
773 std::vector<DlColor> colors = {
774 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
775 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
776 std::vector<Scalar> stops = {0.0, 1.0};
777
778 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {50, 50},
779 stops.size(), colors.data(),
780 stops.data(), tile_mode));
781
782 SkPath path;
783 path.moveTo(20, 20);
784 path.quadTo({60, 20}, {60, 60});
785 path.close();
786 path.moveTo(60, 20);
787 path.quadTo({60, 60}, {20, 60});
788
789 builder.Scale(scale, scale);
790
791 if (add_circle_clip) {
792 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
793 Color::Red());
794 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
795 Color::Red());
796 auto [handle_a, handle_b] =
797 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
798
799 SkMatrix screen_to_canvas;
800 if (!builder.GetTransform().invert(&screen_to_canvas)) {
801 return nullptr;
802 }
803 Matrix ip_matrix = ToMatrix(screen_to_canvas);
804 Point point_a = ip_matrix * handle_a * GetContentScale();
805 Point point_b = ip_matrix * handle_b * GetContentScale();
806
807 Point middle = (point_a + point_b) / 2;
808 auto radius = point_a.GetDistance(middle);
809 SkPath circle;
810 circle.addCircle(middle.x, middle.y, radius);
811 builder.ClipPath(circle);
812 }
813
814 for (auto join :
815 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
816 paint.setStrokeJoin(join);
817 for (auto cap :
818 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
819 paint.setStrokeCap(cap);
820 builder.DrawPath(path, paint);
821 builder.Translate(80, 0);
822 }
823 builder.Translate(-240, 60);
824 }
825
826 return builder.Build();
827 };
828
829 ASSERT_TRUE(OpenPlaygroundHere(callback));
830 }

References impeller::DrawPlaygroundLine(), impeller::TPoint< T >::GetDistance(), scale, impeller::Color::ToARGB(), impeller::skia_conversions::ToMatrix(), impeller::TPoint< T >::x, x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [226/494]

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

Definition at line 900 of file aiks_dl_basic_unittests.cc.

900 {
901 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
902
903 DisplayListBuilder builder;
904 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
905
906 DlPaint paint;
907 paint.setColor(DlColor::kWhite());
908 builder.DrawPaint(paint);
909
910 // Translation
911 {
912 DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
913 DlPaint paint;
914 paint.setColorSource(DlColorSource::MakeImage(
915 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
916 DlImageSampling::kNearestNeighbor, &matrix));
917
918 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
919 }
920
921 // Rotation/skew
922 {
923 builder.Save();
924 builder.Rotate(45);
925 DlPaint paint;
926
927 Matrix matrix(1, -1, 0, 0, //
928 1, 1, 0, 0, //
929 0, 0, 1, 0, //
930 0, 0, 0, 1);
931 paint.setColorSource(DlColorSource::MakeImage(
932 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
933 DlImageSampling::kNearestNeighbor, &matrix));
934 builder.DrawRect(SkRect::MakeLTRB(100, 0, 200, 100), paint);
935 builder.Restore();
936 }
937
938 // Scale
939 {
940 builder.Translate(100, 0);
941 builder.Scale(100, 100);
942 DlPaint paint;
943
944 DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
945 paint.setColorSource(DlColorSource::MakeImage(
946 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
947 DlImageSampling::kNearestNeighbor, &matrix));
948
949 builder.DrawRect(SkRect::MakeLTRB(0, 0, 1, 1), paint);
950 }
951
952 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
953 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [227/494]

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

Definition at line 667 of file aiks_dl_unittests.cc.

667 {
668 DisplayListBuilder builder;
669 builder.Scale(GetContentScale().x, GetContentScale().y);
670
671 auto test = [&builder](const std::shared_ptr<DlImageFilter>& filter) {
672 auto DrawLine = [&builder](const SkPoint& p0, const SkPoint& p1,
673 const DlPaint& p) {
674 DlPaint paint = p;
675 paint.setDrawStyle(DlDrawStyle::kStroke);
676 builder.DrawPath(SkPath::Line(p0, p1), paint);
677 };
678 // Registration marks for the edge of the SaveLayer
679 DlPaint paint;
680 paint.setColor(DlColor::kWhite());
681 DrawLine(SkPoint::Make(75, 100), SkPoint::Make(225, 100), paint);
682 DrawLine(SkPoint::Make(75, 200), SkPoint::Make(225, 200), paint);
683 DrawLine(SkPoint::Make(100, 75), SkPoint::Make(100, 225), paint);
684 DrawLine(SkPoint::Make(200, 75), SkPoint::Make(200, 225), paint);
685
686 DlPaint save_paint;
687 save_paint.setImageFilter(filter);
688 SkRect bounds = SkRect::MakeLTRB(100, 100, 200, 200);
689 builder.SaveLayer(&bounds, &save_paint);
690
691 {
692 // DrawPaint to verify correct behavior when the contents are unbounded.
693 DlPaint paint;
694 paint.setColor(DlColor::kYellow());
695 builder.DrawPaint(paint);
696
697 // Contrasting rectangle to see interior blurring
698 paint.setColor(DlColor::kBlue());
699 builder.DrawRect(SkRect::MakeLTRB(125, 125, 175, 175), paint);
700 }
701 builder.Restore();
702 };
703
704 test(DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal));
705
706 builder.Translate(200.0, 0.0);
707
708 test(DlImageFilter::MakeDilate(10.0, 10.0));
709
710 builder.Translate(200.0, 0.0);
711
712 test(DlImageFilter::MakeErode(10.0, 10.0));
713
714 builder.Translate(-400.0, 200.0);
715
716 DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(10));
717
718 auto rotate_filter =
719 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
720 test(rotate_filter);
721
722 builder.Translate(200.0, 0.0);
723
724 const float m[20] = {
725 0, 1, 0, 0, 0, //
726 0, 0, 1, 0, 0, //
727 1, 0, 0, 0, 0, //
728 0, 0, 0, 1, 0 //
729 };
730 auto rgb_swap_filter =
731 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(m));
732 test(rgb_swap_filter);
733
734 builder.Translate(200.0, 0.0);
735
736 test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter));
737
738 builder.Translate(-400.0, 200.0);
739
740 test(rotate_filter->makeWithLocalMatrix(
741 DlMatrix::MakeTranslation({25.0, 25.0})));
742
743 builder.Translate(200.0, 0.0);
744
745 test(rgb_swap_filter->makeWithLocalMatrix(
746 DlMatrix::MakeTranslation({25.0, 25.0})));
747
748 builder.Translate(200.0, 0.0);
749
750 test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter)
751 ->makeWithLocalMatrix(DlMatrix::MakeTranslation({25.0, 25.0})));
752
753 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
754 }

References x.

## ◆ TEST_P() [228/494]

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

Definition at line 231 of file aiks_dl_unittests.cc.

231 {
232 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
233 builder.Scale(GetContentScale().x, GetContentScale().y);
234
235 DlPaint save_paint;
236 save_paint.setImageFilter(
237 DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal));
238 builder.SaveLayer(nullptr, &save_paint);
239
240 {
241 // DrawPaint to verify correct behavior when the contents are unbounded.
242 DlPaint draw_paint;
243 draw_paint.setColor(DlColor::kYellow());
244 builder.DrawPaint(draw_paint);
245
246 // Contrasting rectangle to see interior blurring
247 DlPaint draw_rect;
248 draw_rect.setColor(DlColor::kBlue());
249 builder.DrawRect(SkRect::MakeLTRB(125, 125, 175, 175), draw_rect);
250 }
251 builder.Restore();
252
253 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
254 }

References x.

## ◆ TEST_P() [229/494]

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

Definition at line 111 of file aiks_dl_unittests.cc.

111 {
112 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
113
114 DlPaint paint;
115 paint.setColorFilter(DlColorFilter::MakeLinearToSrgbGamma());
116 builder.SaveLayer(nullptr, &paint);
117
118 builder.Translate(500, 300);
119 builder.Rotate(120); // 120 deg.
120
121 DlPaint draw_paint;
122 draw_paint.setColor(DlColor::kBlue());
123 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
124
125 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
126 }

## ◆ TEST_P() [230/494]

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

Definition at line 760 of file aiks_dl_blur_unittests.cc.

760 {
761 Scalar sigma = 70;
762 auto callback = [&]() -> sk_sp<DisplayList> {
763 if (AiksTest::ImGuiBegin("Controls", nullptr,
764 ImGuiWindowFlags_AlwaysAutoResize)) {
765 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
766 ImGui::End();
767 }
768
769 DisplayListBuilder builder;
770 builder.Scale(GetContentScale().x, GetContentScale().y);
771
772 DlPaint paint;
773 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
774 builder.DrawPaint(paint);
775
776 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
777
778 builder.Transform(SkMatrix::Translate(100, 100) *
779 SkMatrix::Scale(0.5, 0.5));
780
781 paint.setColorSource(DlColorSource::MakeImage(
782 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
783 DlImageSampling::kMipmapLinear));
784 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
785
786 builder.DrawRect(SkRect::MakeXYWH(0, 0, boston->GetSize().width,
787 boston->GetSize().height),
788 paint);
789
790 return builder.Build();
791 };
792 ASSERT_TRUE(OpenPlaygroundHere(callback));
793 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [231/494]

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

Definition at line 475 of file aiks_dl_blur_unittests.cc.

475 {
476 // Making sure this test is run on a wide gamut enabled backend
477 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
478 PixelFormat::kB10G10R10A10XR);
479
480 DisplayListBuilder builder;
481 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
482
483 DlPaint paint;
484 paint.setColor(DlColor::kBlue());
485 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
486
487 // Zero height above
488 builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint);
489 // Regular rect
490 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
491 // Zero width to the right
492 builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint);
493
494 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
495 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [232/494]

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

Definition at line 731 of file aiks_dl_blur_unittests.cc.

731 {
732 Scalar sigma = 30;
733 auto callback = [&]() -> sk_sp<DisplayList> {
734 if (AiksTest::ImGuiBegin("Controls", nullptr,
735 ImGuiWindowFlags_AlwaysAutoResize)) {
736 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
737 ImGui::End();
738 }
739
740 DisplayListBuilder builder;
741 builder.Scale(GetContentScale().x, GetContentScale().y);
742
743 DlPaint paint;
744 paint.setColor(DlColor::kGreen());
745 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
746
747 builder.DrawImage(
748 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
749 SkPoint{200, 200}, DlImageSampling::kNearestNeighbor, &paint);
750
751 DlPaint red;
752 red.setColor(DlColor::kRed());
753 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
754
755 return builder.Build();
756 };
757 ASSERT_TRUE(OpenPlaygroundHere(callback));
758 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [233/494]

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

Definition at line 462 of file aiks_dl_blur_unittests.cc.

462 {
463 DisplayListBuilder builder;
464
465 DlPaint paint;
466 paint.setColor(DlColor::kBlue());
467 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 0));
468
469 builder.DrawCircle(SkPoint{300, 300}, 200, paint);
470 builder.DrawRect(SkRect::MakeLTRB(100, 300, 500, 600), paint);
471
472 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
473 }

## ◆ TEST_P() [234/494]

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

Definition at line 1527 of file aiks_dl_basic_unittests.cc.

1527 {
1528 if (GetBackend() == PlaygroundBackend::kVulkan) {
1529 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
1530 }
1531 DisplayListBuilder builder(SkRect::MakeSize(SkSize::Make(1000, 1000)));
1532
1533 auto filter = DlImageFilter::MakeMatrix(
1534 DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
1535
1536 DlPaint paint;
1537 paint.setImageFilter(filter);
1538 builder.SaveLayer(nullptr, &paint);
1539 {
1540 DlPaint paint;
1541 paint.setColor(DlColor::kRed());
1542 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100000, 100000), paint);
1543 }
1544 builder.Restore();
1545
1546 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1547 }

References impeller::kVulkan.

## ◆ TEST_P() [235/494]

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

Definition at line 756 of file aiks_dl_unittests.cc.

756 {
757 DisplayListBuilder builder;
758
759 DlPaint paint;
760 paint.setColor(DlColor::kBlack());
761 builder.DrawPaint(paint);
762 builder.SaveLayer(nullptr, nullptr);
763 {
764 DlPaint paint;
765 paint.setColor(DlColor::kGreen().withAlpha(0.5 * 255));
766 paint.setBlendMode(DlBlendMode::kPlus);
767
768 DlPaint rect_paint;
769 rect_paint.setColor(DlColor::kRed());
770 rect_paint.setStrokeWidth(4);
771 rect_paint.setDrawStyle(DlDrawStyle::kStroke);
772 builder.DrawRect(SkRect::MakeLTRB(0, 0, 300, 300), rect_paint);
773 builder.DrawCircle(SkPoint::Make(200, 200), 100, paint);
774 // Should render a second circle, centered on the bottom-right-most edge of
775 // the circle.
776 DlMatrix matrix = DlMatrix::MakeTranslation({(100 + 100 * k1OverSqrt2),
777 (100 + 100 * k1OverSqrt2)}) *
778 DlMatrix::MakeScale({0.5, 0.5, 1}) *
779 DlMatrix::MakeTranslation({-100, -100});
780 auto backdrop_filter =
781 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
782 builder.SaveLayer(nullptr, nullptr, backdrop_filter.get());
783 builder.Restore();
784 }
785 builder.Restore();
786
787 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
788 }

References impeller::k1OverSqrt2.

## ◆ TEST_P() [236/494]

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

Definition at line 1005 of file aiks_dl_basic_unittests.cc.

1006 {
1007 DisplayListBuilder builder;
1008 builder.Scale(GetContentScale().x, GetContentScale().y);
1009 builder.Translate(100, 100);
1010 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1011 // +300 translation applied by a SaveLayer image filter.
1012
1013 DlPaint paint;
1014 paint.setImageFilter(DlImageFilter::MakeMatrix(
1015 DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1016 DlImageSampling::kNearestNeighbor));
1017 builder.SaveLayer(nullptr, &paint);
1018
1019 DlPaint circle_paint;
1020 circle_paint.setColor(DlColor::kGreen());
1021 builder.DrawCircle(SkPoint{-150, 0}, 50, circle_paint);
1022 builder.Restore();
1023
1024 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1025 }

References x.

## ◆ TEST_P() [237/494]

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

Definition at line 984 of file aiks_dl_basic_unittests.cc.

984 {
985 DisplayListBuilder builder;
986 builder.Scale(GetContentScale().x, GetContentScale().y);
987 builder.Translate(100, 100);
988 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
989 // +300 translation applied by a SaveLayer image filter.
990 DlPaint paint;
991 DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
992 paint.setImageFilter(
993 DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
994 builder.SaveLayer(nullptr, &paint);
995
996 DlPaint circle_paint;
997 circle_paint.setColor(DlColor::kGreen());
998 builder.DrawCircle(SkPoint{-300, 0}, 100, circle_paint);
999 builder.Restore();
1000
1001 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1002 }

References x.

## ◆ TEST_P() [238/494]

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

Definition at line 635 of file aiks_dl_unittests.cc.

635 {
636 Scalar scale = 2.0;
637 auto callback = [&]() -> sk_sp<DisplayList> {
638 if (AiksTest::ImGuiBegin("Controls", nullptr,
639 ImGuiWindowFlags_AlwaysAutoResize)) {
640 ImGui::SliderFloat("Scale", &scale, 1, 2);
641 ImGui::End();
642 }
643 DisplayListBuilder builder;
644 builder.Scale(GetContentScale().x, GetContentScale().y);
645 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
646
647 builder.Translate(600, -200);
648
649 DlMatrix matrix = DlMatrix::MakeScale({scale, scale, 1});
650 DlPaint paint;
651 paint.setImageFilter(
652 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
653 builder.SaveLayer(nullptr, &paint);
654
655 DlPaint rect_paint;
656 rect_paint.setAlpha(0.5 * 255);
657 builder.DrawImage(image, SkPoint{0, 0}, DlImageSampling::kLinear,
658 &rect_paint);
659 builder.Restore();
660
661 return builder.Build();
662 };
663
664 ASSERT_TRUE(OpenPlaygroundHere(callback));
665 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), scale, and x.

## ◆ TEST_P() [239/494]

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

Definition at line 790 of file aiks_dl_unittests.cc.

790 {
791 DisplayListBuilder builder;
792
793 DlPaint paint;
794 paint.setColor(DlColor::kBlack());
795 builder.DrawPaint(paint);
796 builder.SaveLayer(nullptr, nullptr);
797 {
798 paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
799 paint.setBlendMode(DlBlendMode::kPlus);
800 builder.DrawCircle(SkPoint{200, 200}, 100, paint);
801 // Should render a second circle, centered on the bottom-right-most edge of
802 // the circle.
803
804 DlMatrix matrix = DlMatrix::MakeTranslation({(200 + 100 * k1OverSqrt2),
805 (200 + 100 * k1OverSqrt2)}) *
806 DlMatrix::MakeScale({0.5, 0.5, 1}) *
807 DlMatrix::MakeTranslation({-200, -200});
808 DlPaint save_paint;
809 save_paint.setImageFilter(
810 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
811
812 builder.SaveLayer(nullptr, &save_paint);
813
814 DlPaint circle_paint;
815 circle_paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
816 circle_paint.setBlendMode(DlBlendMode::kPlus);
817 builder.DrawCircle(SkPoint{200, 200}, 100, circle_paint);
818 builder.Restore();
819 }
820 builder.Restore();
821
822 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
823 }

References impeller::k1OverSqrt2.

## ◆ TEST_P() [240/494]

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

Definition at line 487 of file aiks_dl_unittests.cc.

487 {
488 TextureDescriptor texture_descriptor;
489 texture_descriptor.size = ISize{1024, 1024};
490 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
491 texture_descriptor.storage_mode = StorageMode::kHostVisible;
492 texture_descriptor.mip_count = texture_descriptor.size.MipCount();
493
494 std::vector<uint8_t> bytes(4194304);
495 bool alternate = false;
496 for (auto i = 0u; i < 4194304; i += 4) {
497 if (alternate) {
498 bytes[i] = 255;
499 bytes[i + 1] = 0;
500 bytes[i + 2] = 0;
501 bytes[i + 3] = 255;
502 } else {
503 bytes[i] = 0;
504 bytes[i + 1] = 255;
505 bytes[i + 2] = 0;
506 bytes[i + 3] = 255;
507 }
508 alternate = !alternate;
509 }
510
511 ASSERT_EQ(texture_descriptor.GetByteSizeOfBaseMipLevel(), bytes.size());
512 auto mapping = std::make_shared<fml::NonOwnedMapping>(
513 bytes.data(), // data
514 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
515 );
516 auto texture =
517 GetContext()->GetResourceAllocator()->CreateTexture(texture_descriptor);
518
519 auto device_buffer =
520 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
521 auto command_buffer = GetContext()->CreateCommandBuffer();
522 auto blit_pass = command_buffer->CreateBlitPass();
523
524 blit_pass->AddCopy(DeviceBuffer::AsBufferView(std::move(device_buffer)),
525 texture);
526 blit_pass->GenerateMipmap(texture);
527 EXPECT_TRUE(blit_pass->EncodeCommands());
528 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({command_buffer}).ok());
529
530 auto image = DlImageImpeller::Make(texture);
531
532 DisplayListBuilder builder;
533 builder.DrawImageRect(
534 image,
535 SkRect::MakeSize(
536 SkSize::Make(texture->GetSize().width, texture->GetSize().height)),
537 SkRect::MakeLTRB(0, 0, 100, 100), DlImageSampling::kMipmapLinear);
538
539 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
540 }

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

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

Definition at line 1549 of file aiks_dl_basic_unittests.cc.

1549 {
1550 Scalar width = 200.f;
1551 Scalar height = 60.f;
1552 Scalar corner = 1.f;
1553 auto callback = [&]() -> sk_sp<DisplayList> {
1554 if (AiksTest::ImGuiBegin("Controls", nullptr,
1555 ImGuiWindowFlags_AlwaysAutoResize)) {
1556 ImGui::SliderFloat("width", &width, 0, 200);
1557 ImGui::SliderFloat("height", &height, 0, 200);
1558 ImGui::SliderFloat("corner", &corner, 0, 1);
1559 ImGui::End();
1560 }
1561
1562 DisplayListBuilder builder;
1563 builder.Scale(GetContentScale().x, GetContentScale().y);
1564
1565 DlPaint background_paint;
1566 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
1567 builder.DrawPaint(background_paint);
1568
1569 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
1570 std::vector<Scalar> stops = {0.0, 1.0};
1571
1572 DlPaint paint;
1573 auto gradient = DlColorSource::MakeLinear(
1574 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
1575 paint.setColorSource(gradient);
1576 paint.setColor(DlColor::kWhite());
1577 paint.setDrawStyle(DlDrawStyle::kStroke);
1578 paint.setStrokeWidth(20);
1579
1580 builder.Save();
1581 builder.Translate(100, 100);
1582
1583 Scalar corner_x = ((1 - corner) * 50) + 50;
1584 Scalar corner_y = corner * 50 + 50;
1585 SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, width, height),
1586 corner_x, corner_y);
1587 builder.DrawRRect(rrect, paint);
1588 builder.Restore();
1589 return builder.Build();
1590 };
1591 ASSERT_TRUE(OpenPlaygroundHere(callback));
1592 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [242/494]

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(SkPoint{150, 200}, 100, paint);
180
181 paint.setColor(DlColor::RGBA(0, 1, 0, 0.5));
182 builder.DrawCircle(SkPoint{250, 200}, 100, paint);
183
184 paint.setBlendMode(DlBlendMode::kPlus);
185
186 paint.setColor(DlColor::kRed());
187 builder.DrawCircle(SkPoint{450, 250}, 100, paint);
188
189 paint.setColor(DlColor::kGreen());
190 builder.DrawCircle(SkPoint{550, 250}, 100, paint);
191
192 paint.setColor(DlColor::kBlue());
193 builder.DrawCircle(SkPoint{500, 150}, 100, paint);
194
195 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
196 }

## ◆ TEST_P() [243/494]

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

Definition at line 1501 of file aiks_dl_basic_unittests.cc.

1501 {
1502 DisplayListBuilder builder;
1503
1504 // Should render a green square in the middle of a blue circle.
1505 DlPaint paint;
1506 builder.SaveLayer(nullptr, &paint);
1507 {
1508 builder.Translate(100, 100);
1509 paint.setColor(DlColor::kBlue());
1510 builder.DrawCircle(SkPoint::Make(200, 200), 200, paint);
1511 builder.ClipRect(SkRect::MakeXYWH(100, 100, 200, 200));
1512
1513 paint.setColor(DlColor::kGreen());
1514 paint.setBlendMode(DlBlendMode::kSrcOver);
1515 paint.setImageFilter(DlImageFilter::MakeColorFilter(
1516 DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
1517 builder.DrawCircle(SkPoint::Make(200, 200), 200, paint);
1518 builder.Restore();
1519 }
1520
1521 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1522 }

## ◆ TEST_P() [244/494]

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

Definition at line 600 of file aiks_dl_unittests.cc.

600 {
601 auto context = MakeContext();
602 std::weak_ptr<Texture> weak_texture;
603
604 {
605 auto texture = CreateTextureForFixture("table_mountain_nx.png");
606 weak_texture = texture;
607
608 DisplayListBuilder builder;
609 builder.Scale(GetContentScale().x, GetContentScale().y);
610 builder.Translate(100.0f, 100.0f);
611
612 DlPaint paint;
613 paint.setColorSource(DlColorSource::MakeImage(
614 DlImageImpeller::Make(texture), DlTileMode::kClamp, DlTileMode::kClamp,
615 DlImageSampling::kLinear, nullptr));
616
617 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
618
619 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
620 }
621
622 // See https://github.com/flutter/flutter/issues/134751.
623 //
624 // If the fence waiter was working this may not be released by the end of the
625 // scope above. Adding a manual shutdown so that future changes to the fence
626 // waiter will not flake this test.
627 context->Shutdown();
628
629 // The texture should be released by now.
630 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
631 "by the backend, it should be "
632 "released.";
633 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [245/494]

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 DlColorFilter::MakeBlend(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() [246/494]

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

Definition at line 1357 of file aiks_dl_basic_unittests.cc.

1357 {
1358 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1359 DisplayListBuilder builder;
1360 DlPaint paint;
1361
1362 paint.setColor(DlColor::kBlack());
1363 SkRect rect = SkRect::MakeXYWH(25, 25, 25, 25);
1364 builder.DrawRect(rect, paint);
1365
1366 builder.Translate(10, 10);
1367
1368 DlPaint save_paint;
1369 builder.SaveLayer(nullptr, &save_paint);
1370
1371 paint.setColor(DlColor::kGreen());
1372 builder.DrawRect(rect, paint);
1373
1374 builder.Restore();
1375
1376 builder.Translate(10, 10);
1377 paint.setColor(DlColor::kRed());
1378 builder.DrawRect(rect, paint);
1379
1380 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1381 }

## ◆ TEST_P() [247/494]

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

Definition at line 1449 of file aiks_dl_basic_unittests.cc.

1449 {
1450 DisplayListBuilder builder;
1451
1452 builder.Scale(GetContentScale().x, GetContentScale().y);
1453 builder.Translate(100, 100);
1454
1455 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
1456 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
1457 builder.SaveLayer(nullptr, &paint);
1458 builder.DrawImage(texture, SkPoint{}, DlImageSampling::kLinear);
1459 builder.Restore();
1460 };
1461
1462 DlPaint effect_paint;
1463 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
1464 draw_image_layer(effect_paint);
1465
1466 builder.Translate(300, 300);
1467 builder.Scale(3, 3);
1468 draw_image_layer(effect_paint);
1469
1470 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1471 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [248/494]

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

Definition at line 566 of file aiks_dl_unittests.cc.

566 {
567 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
568
569 // Replace part of the texture with a red rectangle.
570 std::vector<uint8_t> bytes(100 * 100 * 4);
571 for (auto i = 0u; i < bytes.size(); i += 4) {
572 bytes[i] = 255;
573 bytes[i + 1] = 0;
574 bytes[i + 2] = 0;
575 bytes[i + 3] = 255;
576 }
577 auto mapping =
578 std::make_shared<fml::NonOwnedMapping>(bytes.data(), bytes.size());
579 auto device_buffer =
580 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
581 auto cmd_buffer = GetContext()->CreateCommandBuffer();
582 auto blit_pass = cmd_buffer->CreateBlitPass();
583 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), bridge,
584 IRect::MakeLTRB(50, 50, 150, 150));
585
586 auto did_submit =
587 blit_pass->EncodeCommands() &&
588 GetContext()->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok();
589 ASSERT_TRUE(did_submit);
590
591 auto image = DlImageImpeller::Make(bridge);
592
593 DisplayListBuilder builder;
594 builder.DrawImage(image, SkPoint{0, 0}, {});
595
596 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
597 }

References impeller::DeviceBuffer::AsBufferView(), impeller::DlImageImpeller::Make(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST_P() [249/494]

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

Definition at line 1383 of file aiks_dl_basic_unittests.cc.

1383 {
1384 DisplayListBuilder builder;
1385 DlPaint paint;
1386 SkRect rect = SkRect::MakeXYWH(0, 0, 1000, 1000);
1387
1388 // Black, green, and red squares offset by [10, 10].
1389 {
1390 DlPaint save_paint;
1391 SkRect bounds = SkRect::MakeXYWH(25, 25, 25, 25);
1392 builder.SaveLayer(&bounds, &save_paint);
1393 paint.setColor(DlColor::kBlack());
1394 builder.DrawRect(rect, paint);
1395 builder.Restore();
1396 }
1397
1398 {
1399 DlPaint save_paint;
1400 SkRect bounds = SkRect::MakeXYWH(35, 35, 25, 25);
1401 builder.SaveLayer(&bounds, &save_paint);
1402 paint.setColor(DlColor::kGreen());
1403 builder.DrawRect(rect, paint);
1404 builder.Restore();
1405 }
1406
1407 {
1408 DlPaint save_paint;
1409 SkRect bounds = SkRect::MakeXYWH(45, 45, 25, 25);
1410 builder.SaveLayer(&bounds, &save_paint);
1411 paint.setColor(DlColor::kRed());
1412 builder.DrawRect(rect, paint);
1413 builder.Restore();
1414 }
1415
1416 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1417 }

## ◆ TEST_P() [250/494]

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 }

References x.

## ◆ TEST_P() [251/494]

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

Definition at line 736 of file aiks_dl_basic_unittests.cc.

736 {
737 DisplayListBuilder builder;
738 builder.Scale(GetContentScale().x, GetContentScale().y);
739 DlPaint paint;
740 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
741
742 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
743
744 paint.setColor(
745 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
746 Scalar y = 100.0f;
747 for (int i = 0; i < 5; i++) {
748 Scalar x = (i + 1) * 100;
749 Scalar radius = x / 10.0f;
750 builder.DrawRect(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
751 radius, 60.0f - radius),
752 paint);
753 }
754
755 paint.setColor(DlColor::kBlue());
756 y += 100.0f;
757 for (int i = 0; i < 5; i++) {
758 Scalar x = (i + 1) * 100;
759 Scalar radius = x / 10.0f;
760 builder.DrawCircle(SkPoint{x + 25, y + 25}, radius, paint);
761 }
762
763 paint.setColor(DlColor::kGreen());
764 y += 100.0f;
765 for (int i = 0; i < 5; i++) {
766 Scalar x = (i + 1) * 100;
767 Scalar radius = x / 10.0f;
768 builder.DrawOval(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
769 radius, 60.0f - radius),
770 paint);
771 }
772
773 paint.setColor(
774 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
775 y += 100.0f;
776 for (int i = 0; i < 5; i++) {
777 Scalar x = (i + 1) * 100;
778 Scalar radius = x / 20.0f;
779 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f),
780 radius, radius),
781 paint);
782 }
783
784 paint.setColor(
785 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
786 y += 100.0f;
787 for (int i = 0; i < 5; i++) {
788 Scalar x = (i + 1) * 100;
789 Scalar radius = x / 20.0f;
790 builder.DrawRRect(
791 SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, 5.0f),
792 paint);
793 }
794
795 auto dl = builder.Build();
796 ASSERT_TRUE(OpenPlaygroundHere(dl));
797 }

References x.

## ◆ TEST_P() [252/494]

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 }

References x.

## ◆ TEST_P() [253/494]

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::alpha, impeller::Color::Black(), impeller::Color::blue, impeller::DrawPlaygroundLine(), impeller::Color::green, impeller::AiksPlayground::ImGuiBegin(), impeller::Color::red, impeller::Color::Red(), scale, impeller::Color::WithAlpha(), and x.

## ◆ TEST_P() [254/494]

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

Definition at line 128 of file aiks_dl_unittests.cc.

128 {
129 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
130
131 DlPaint paint;
132 paint.setColorFilter(DlColorFilter::MakeLinearToSrgbGamma());
133 builder.SaveLayer(nullptr, &paint);
134
135 builder.Translate(500, 300);
136 builder.Rotate(120); // 120 deg
137
138 DlPaint draw_paint;
139 draw_paint.setColor(DlColor::kBlue());
140 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
141
142 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
143 }

## ◆ TEST_P() [255/494]

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

Definition at line 494 of file aiks_dl_basic_unittests.cc.

494 {
495 DisplayListBuilder builder;
496 builder.Scale(GetContentScale().x, GetContentScale().y);
497 DlPaint paint;
498 const int color_count = 3;
499 DlColor colors[color_count] = {
500 DlColor::kBlue(),
501 DlColor::kGreen(),
502 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
503 };
504
505 paint.setColor(DlColor::kWhite());
506 builder.DrawPaint(paint);
507
508 int c_index = 0;
509
510 auto draw = [&paint, &colors, &c_index](DlCanvas& canvas, SkPoint center,
511 Scalar r, Scalar dr, int n) {
512 for (int i = 0; i < n; i++) {
513 paint.setColor(colors[(c_index++) % color_count]);
514 canvas.DrawCircle(center, r, paint);
515 r += dr;
516 }
517 };
518
519 paint.setDrawStyle(DlDrawStyle::kStroke);
520 paint.setStrokeWidth(1);
521 draw(builder, {10, 10}, 2, 2, 14); // r = [2, 28], covers [1,29]
522 paint.setStrokeWidth(5);
523 draw(builder, {10, 10}, 35, 10, 56); // r = [35, 585], covers [30,590]
524
525 DlColor gradient_colors[7] = {
526 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
527 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
528 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
529 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
530 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
531 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
532 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
533 };
534 DlScalar stops[7] = {
535 0.0,
536 (1.0 / 6.0) * 1,
537 (1.0 / 6.0) * 2,
538 (1.0 / 6.0) * 3,
539 (1.0 / 6.0) * 4,
540 (1.0 / 6.0) * 5,
541 1.0,
542 };
543 auto texture = CreateTextureForFixture("airplane.jpg",
544 /*enable_mipmapping=*/true);
545 auto image = DlImageImpeller::Make(texture);
546
547 paint.setColorSource(DlColorSource::MakeRadial(
548 {500, 600}, 75, 7, gradient_colors, stops, DlTileMode::kMirror));
549 draw(builder, {500, 600}, 5, 10, 10);
550
551 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
552 paint.setColorSource(DlColorSource::MakeImage(
553 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
554 DlImageSampling::kNearestNeighbor, &local_matrix));
555 draw(builder, {800, 300}, 5, 10, 10);
556
557 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
558 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [256/494]

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

Definition at line 543 of file aiks_dl_unittests.cc.

543 {
544 SkPath path;
545 path.moveTo(0, 400)
546 .lineTo(0, 0)
547 .lineTo(400, 0)
548 // MoveTo implicitly adds a contour, ensure that close doesn't
549 // add another nearly-empty contour.
550 .moveTo(0, 400)
551 .close();
552
553 DisplayListBuilder builder;
554 builder.Translate(50, 50);
555
556 DlPaint paint;
557 paint.setColor(DlColor::kBlue());
558 paint.setStrokeCap(DlStrokeCap::kRound);
559 paint.setStrokeWidth(10);
560 paint.setDrawStyle(DlDrawStyle::kStroke);
561 builder.DrawPath(path, paint);
562
563 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
564 }

## ◆ TEST_P() [257/494]

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

Definition at line 955 of file aiks_dl_basic_unittests.cc.

955 {
956 DisplayListBuilder builder;
957
958 // Use a non-srcOver blend mode to ensure that we don't detect this as an
959 // opacity peephole optimization.
960 DlPaint paint;
961 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
962 paint.setBlendMode(DlBlendMode::kSrc);
963
964 SkRect bounds = SkRect::MakeLTRB(0, 0, 200, 200);
965 builder.SaveLayer(&bounds, &paint);
966
967 paint.setColor(DlColor::kTransparent());
968 paint.setBlendMode(DlBlendMode::kSrc);
969 builder.DrawPaint(paint);
970 builder.Restore();
971
972 paint.setColor(DlColor::kBlue());
973 paint.setBlendMode(DlBlendMode::kDstOver);
974 builder.SaveLayer(nullptr, &paint);
975 builder.Restore();
976
977 // This playground should appear blank on CI since we are only drawing
978 // transparent black. If the clear color optimization is broken, the texture
979 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
980 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
981 }

## ◆ TEST_P() [258/494]

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

Definition at line 376 of file canvas_unittests.cc.

376 {
377 ContentContext context(GetContext(), nullptr);
378 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
379 /*requires_readback=*/true);
380
381 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
382 EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
383 } else {
384 EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
385 }
386 }

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

## ◆ TEST_P() [259/494]

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

Definition at line 465 of file aiks_dl_text_unittests.cc.

465 {
466 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
467 ASSERT_NE(mapping, nullptr);
468
469 Scalar font_size = 100;
470 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
471 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
472
473 DlPaint text_paint;
474 text_paint.setColor(DlColor::kBlue());
475
476 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
477 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
478 std::vector<Scalar> stops = {
479 0.0,
480 1.0,
481 };
482 text_paint.setColorSource(DlColorSource::MakeLinear(
483 /*start_point=*/DlPoint(0, 0), //
484 /*end_point=*/DlPoint(100, 100), //
485 /*stop_count=*/2, //
486 /*colors=*/colors.data(), //
487 /*stops=*/stops.data(), //
488 /*tile_mode=*/DlTileMode::kRepeat //
489 ));
490
491 DisplayListBuilder builder;
492 builder.Translate(100, 100);
493 builder.Rotate(45);
494
495 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
496 ASSERT_NE(blob, nullptr);
497 auto frame = MakeTextFrameFromTextBlobSkia(blob);
498 builder.DrawTextFrame(frame, 0, 0, text_paint);
499
500 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
501 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [260/494]

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

Definition at line 187 of file aiks_dl_text_unittests.cc.

187 {
188 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
189 std::array<Scalar, 20> phase_offsets = {
190 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
191 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
192 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
193 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
194 auto callback = [&]() -> sk_sp<DisplayList> {
195 static float font_size = 20;
196 static float phase_variation = 0.2;
197 static float speed = 0.5;
198 static float magnitude = 100;
199 if (AiksTest::ImGuiBegin("Controls", nullptr,
200 ImGuiWindowFlags_AlwaysAutoResize)) {
201 ImGui::SliderFloat("Font size", &font_size, 5, 50);
202 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
203 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
204 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
205 ImGui::End();
206 }
207
208 DisplayListBuilder builder;
209 builder.Scale(GetContentScale().x, GetContentScale().y);
210
211 for (size_t i = 0; i < phase_offsets.size(); i++) {
212 SkPoint position = SkPoint::Make(
213 200 +
214 magnitude * std::sin((-phase_offsets[i] * k2Pi * phase_variation +
215 GetSecondsElapsed() * speed)), //
216 200 + i * font_size * 1.1 //
217 );
218 if (!RenderTextInCanvasSkia(
219 GetContext(), builder,
220 "the quick brown fox jumped over "
221 "the lazy dog!.?",
222 "Roboto-Regular.ttf",
223 {.font_size = font_size, .position = position})) {
224 return nullptr;
225 }
226 }
227 return builder.Build();
228 };
229
230 ASSERT_TRUE(OpenPlaygroundHere(callback));
231 }

References impeller::k2Pi, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [261/494]

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

Definition at line 359 of file aiks_dl_text_unittests.cc.

359 {
360 DisplayListBuilder builder;
361
362 builder.Scale(GetContentScale().x, GetContentScale().y);
363 DlPaint paint;
364 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
365 builder.DrawPaint(paint);
366
367 builder.Transform(SkM44::ColMajor(Matrix(0.25, -0.3, 0, -0.002, //
368 0, 0.5, 0, 0, //
369 0, 0, 0.3, 0, //
370 100, 100, 0, 1.3)
371 .m));
372 ASSERT_TRUE(RenderTextInCanvasSkia(
373 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
374 "Roboto-Regular.ttf"));
375
376 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
377 }

References RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [262/494]

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

Definition at line 1053 of file aiks_dl_unittests.cc.

1053 {
1054 DisplayListBuilder builder;
1055 Path ip_path = PathBuilder{}
1056 .AddArc(DlRect::MakeLTRB(0, 0, 100, 100), Radians(0),
1057 Radians(3.14 / 2))
1058 .TakePath();
1059 DlPath path = DlPath(ip_path);
1060
1061 builder.DrawPath(path, DlPaint().setColor(DlColor::kRed()));
1062
1063 AiksContext renderer(GetContext(), nullptr);
1064 auto texture =
1065 DisplayListToTexture(builder.Build(), ISize(100, 100), renderer);
1066
1067 // First, Readback the texture data into a host buffer.
1068 impeller::DeviceBufferDescriptor desc;
1069 desc.size = texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
1070 desc.readback = true;
1071 desc.storage_mode = StorageMode::kHostVisible;
1072
1073 auto device_buffer = GetContext()->GetResourceAllocator()->CreateBuffer(desc);
1074 {
1075 auto cmd_buffer = GetContext()->CreateCommandBuffer();
1076 auto blit_pass = cmd_buffer->CreateBlitPass();
1077
1078 blit_pass->AddCopy(texture, device_buffer);
1079 blit_pass->EncodeCommands();
1080
1081 auto latch = std::make_shared<fml::CountDownLatch>(1u);
1082 GetContext()->GetCommandQueue()->Submit(
1083 {cmd_buffer},
1084 [latch](CommandBuffer::Status status) { latch->CountDown(); });
1085 latch->Wait();
1086 }
1087
1088 impeller::TextureDescriptor tex_desc = texture->GetTextureDescriptor();
1089 auto reupload_texture =
1090 GetContext()->GetResourceAllocator()->CreateTexture(tex_desc);
1091
1092 // Next, Re-upload the data into a new texture.
1093 {
1094 auto cmd_buffer = GetContext()->CreateCommandBuffer();
1095 auto blit_pass = cmd_buffer->CreateBlitPass();
1096 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer),
1097 reupload_texture);
1098 blit_pass->ConvertTextureToShaderRead(texture);
1099 blit_pass->EncodeCommands();
1100
1101 auto latch = std::make_shared<fml::CountDownLatch>(1u);
1102 GetContext()->GetCommandQueue()->Submit(
1103 {cmd_buffer},
1104 [latch](CommandBuffer::Status status) { latch->CountDown(); });
1105 latch->Wait();
1106 }
1107
1108 // Draw the results side by side. These should look the same.
1109 DisplayListBuilder canvas;
1110 DlPaint paint = DlPaint();
1111 canvas.DrawRect(
1112 DlRect::MakeLTRB(0, 0, 100, 100),
1113 DlPaint().setColor(DlColor::kBlue()).setDrawStyle(DlDrawStyle::kStroke));
1114 canvas.DrawImage(DlImageImpeller::Make(texture), DlPoint(0, 0),
1115 DlImageSampling::kNearestNeighbor, &paint);
1116
1117 canvas.DrawRect(
1118 DlRect::MakeLTRB(0, 100, 100, 200),
1119 DlPaint().setColor(DlColor::kRed()).setDrawStyle(DlDrawStyle::kStroke));
1120 canvas.DrawImage(DlImageImpeller::Make(reupload_texture), DlPoint(0, 100),
1121 DlImageSampling::kNearestNeighbor, &paint);
1122 OpenPlaygroundHere(canvas.Build());
1123 }

References impeller::PathBuilder::AddArc(), impeller::DeviceBuffer::AsBufferView(), impeller::DisplayListToTexture(), impeller::kHostVisible, impeller::DlImageImpeller::Make(), impeller::DeviceBufferDescriptor::readback, impeller::DeviceBufferDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [263/494]

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

Definition at line 69 of file canvas_unittests.cc.

69 {
70 ContentContext context(GetContext(), nullptr);
71 auto canvas = CreateTestCanvas(context);
72
73 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix());
74
75 // clang-format off
76 canvas->Translate(Vector3(100, 200));
77 ASSERT_MATRIX_NEAR(
78 canvas->GetCurrentTransform(),
79 Matrix( 1, 0, 0, 0,
80 0, 1, 0, 0,
81 0, 0, 1, 0,
82 100, 200, 0, 1));
83
84 canvas->Rotate(Radians(kPiOver2));
85 ASSERT_MATRIX_NEAR(
86 canvas->GetCurrentTransform(),
87 Matrix( 0, 1, 0, 0,
88 -1, 0, 0, 0,
89 0, 0, 1, 0,
90 100, 200, 0, 1));
91
92 canvas->Scale(Vector3(2, 3));
93 ASSERT_MATRIX_NEAR(
94 canvas->GetCurrentTransform(),
95 Matrix( 0, 2, 0, 0,
96 -3, 0, 0, 0,
97 0, 0, 0, 0,
98 100, 200, 0, 1));
99
100 canvas->Translate(Vector3(100, 200));
101 ASSERT_MATRIX_NEAR(
102 canvas->GetCurrentTransform(),
103 Matrix( 0, 2, 0, 0,
104 -3, 0, 0, 0,
105 0, 0, 0, 0,
106 -500, 400, 0, 1));
107 // clang-format on
108 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::kPiOver2.

## ◆ TEST_P() [264/494]

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

Definition at line 145 of file aiks_dl_unittests.cc.

145 {
146 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
147
148 DlPaint paint;
149 paint.setColor(DlColor::kBlue());
150 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
151
152 DlPaint save_paint;
153 save_paint.setColor(DlColor::kBlack().withAlpha(128));
154 builder.SaveLayer(nullptr, &save_paint);
155 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), paint);
156 builder.Restore();
157
158 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
159 }

## ◆ TEST_P() [265/494]

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

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, SkPoint{100, 100}, DlImageSampling::kMipmapLinear);
261
262 DlPaint paint;
263 paint.setColor(DlColor::kBlack().withAlpha(128));
264 builder.SaveLayer(nullptr, &paint);
265 builder.DrawImage(image, SkPoint{100, 500}, DlImageSampling::kMipmapLinear);
266 builder.Restore();
267
268 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
269 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [266/494]

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

Definition at line 341 of file aiks_dl_unittests.cc.

341 {
342 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
343
344 DlPaint paint;
345 paint.setColor(DlColor::kRed());
346 builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), paint);
347
348 DlPaint save_paint;
349 save_paint.setAlpha(128);
350 save_paint.setBlendMode(DlBlendMode::kLighten);
351 builder.SaveLayer(nullptr, &save_paint);
352
353 DlPaint draw_paint;
354 draw_paint.setColor(DlColor::kGreen());
355 builder.DrawCircle(SkPoint{200, 200}, 100, draw_paint);
356 builder.Restore();
357
358 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
359 }

## ◆ TEST_P() [267/494]

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

Definition at line 161 of file aiks_dl_unittests.cc.

161 {
162 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
163
164 DlPaint paint;
165 paint.setColor(DlColor::kBlue());
166 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
167
168 DlPaint save_paint;
169 paint.setColor(DlColor::kBlack().withAlpha(128));
170 paint.setColorFilter(
171 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver));
172 builder.Save();
173 builder.ClipRect(SkRect::MakeXYWH(100, 500, 300, 300));
174 builder.SaveLayer(nullptr, &paint);
175
176 DlPaint draw_paint;
177 draw_paint.setColor(DlColor::kBlue());
178 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
179 builder.Restore();
180 builder.Restore();
181
182 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
183 }

## ◆ TEST_P() [268/494]

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

Definition at line 185 of file aiks_dl_unittests.cc.

185 {
186 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
187
188 DlPaint paint;
189 paint.setColor(DlColor::kBlue());
190 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
191
192 DlPaint save_paint;
193 save_paint.setColor(DlColor::kBlack().withAlpha(128));
194 save_paint.setImageFilter(DlImageFilter::MakeColorFilter(
195 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver)));
196
197 builder.SaveLayer(nullptr, &save_paint);
198
199 DlPaint draw_paint;
200 draw_paint.setColor(DlColor::kBlue());
201 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
202 builder.Restore();
203
204 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
205 }

## ◆ TEST_P() [269/494]

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

Definition at line 207 of file aiks_dl_unittests.cc.

207 {
208 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
209
210 DlPaint paint;
211 paint.setColor(DlColor::kBlue());
212 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
213
214 DlPaint save_paint;
215 save_paint.setColor(DlColor::kBlack().withAlpha(128));
216 save_paint.setColorFilter(
217 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver));
218 builder.Save();
219 builder.ClipRect(SkRect::MakeXYWH(100, 500, 300, 300));
220 builder.SaveLayer(nullptr, &save_paint);
221
222 DlPaint draw_paint;
223 draw_paint.setColor(DlColor::kBlue());
224 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
225 builder.Restore();
226 builder.Restore();
227
228 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
229 }

## ◆ TEST_P() [270/494]

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

Definition at line 315 of file aiks_dl_unittests.cc.

316 {
317 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
318
319 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
320 builder.DrawImage(image, SkPoint{100, 100}, {});
321
322 const float matrix[20] = {
323 1, 0, 0, 0, 0, //
324 0, 1, 0, 0, 0, //
325 0, 0.2, 1, 0, 0, //
326 0, 0, 0, 0.5, 0 //
327 };
328 DlPaint paint;
329 paint.setColor(DlColor::kBlack().withAlpha(128));
330 paint.setImageFilter(
331 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix)));
332 paint.setColorFilter(
333 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kModulate));
334 builder.SaveLayer(nullptr, &paint);
335 builder.DrawImage(image, SkPoint{100, 500}, {});
336 builder.Restore();
337
338 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
339 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [271/494]

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

Definition at line 271 of file aiks_dl_unittests.cc.

271 {
272 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
273
274 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
275 builder.DrawImage(image, SkPoint{100, 100}, {});
276
277 const float matrix[20] = {
278 1, 0, 0, 0, 0, //
279 0, 1, 0, 0, 0, //
280 0, 0, 1, 0, 0, //
281 0, 0, 0, 2, 0 //
282 };
283 DlPaint paint;
284 paint.setColor(DlColor::kBlack().withAlpha(128));
285 paint.setColorFilter(DlColorFilter::MakeMatrix(matrix));
286 builder.SaveLayer(nullptr, &paint);
287 builder.DrawImage(image, SkPoint{100, 500}, {});
288 builder.Restore();
289
290 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
291 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [272/494]

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

Definition at line 293 of file aiks_dl_unittests.cc.

293 {
294 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
295
296 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
297 builder.DrawImage(image, SkPoint{100, 100}, {});
298
299 const float matrix[20] = {
300 1, 0, 0, 0, 0, //
301 0, 1, 0, 0, 0, //
302 0, 0, 1, 0, 0, //
303 0, 0, 0, 2, 0 //
304 };
305 DlPaint paint;
306 paint.setColor(DlColor::kBlack().withAlpha(128));
307 paint.setColorFilter(DlColorFilter::MakeMatrix(matrix));
308 builder.SaveLayer(nullptr, &paint);
309 builder.DrawImage(image, SkPoint{100, 500}, {});
310 builder.Restore();
311
312 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
313 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [273/494]

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

Definition at line 866 of file aiks_dl_unittests.cc.

866 {
867 DisplayListBuilder builder;
868 builder.Save();
869 builder.Scale(1.618, 1.618);
870 SkPath path = SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100));
871
872 builder.DrawShadow(path, flutter::DlColor::kTransparent(), 15, false, 1);
873 builder.Restore();
874
875 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
876 }

## ◆ TEST_P() [274/494]

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

Definition at line 924 of file aiks_dl_gradient_unittests.cc.

924 {
925 DisplayListBuilder builder;
926 DlPaint paint;
927 builder.Translate(100.0f, 0);
928
929 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
930 DlColor::kGreen()};
931 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
932
933 // Inset the start and end point to verify that we do not apply
934 // the fast gradient condition.
935 paint.setColorSource(
936 DlColorSource::MakeLinear({0, 150}, {0, 100}, stops.size(), colors.data(),
937 stops.data(), DlTileMode::kRepeat));
938
939 paint.setColor(DlColor::kWhite());
940 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
941 builder.Translate(400, 0);
942 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
943 paint);
944
945 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
946 }

## ◆ TEST_P() [275/494]

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

Definition at line 96 of file aiks_dl_vertices_unittests.cc.

96 {
97 DisplayListBuilder builder;
98 DlPaint paint;
99 auto image =
100 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
101 auto size = image->impeller_texture()->GetSize();
102
103 paint.setColorSource(
104 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
105
106 std::vector<DlPoint> positions = {
107 DlPoint(0, 0), DlPoint(size.width, 0),
108 DlPoint(0, size.height), DlPoint(size.width, 0),
109 DlPoint(0, 0), DlPoint(size.width, size.height),
110 };
111 std::vector<DlColor> colors = {
112 DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
113 DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
114 DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
115 };
116
117 auto vertices =
118 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
119
120 builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
121 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
122 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [276/494]

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

Definition at line 124 of file aiks_dl_vertices_unittests.cc.

124 {
125 DisplayListBuilder builder;
126 DlPaint paint;
127 auto image =
128 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
129 auto size = image->impeller_texture()->GetSize();
130
131 paint.setColorSource(
132 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
133
134 std::vector<DlPoint> positions = {
135 DlPoint(0, 0), DlPoint(size.width, 0),
136 DlPoint(0, size.height), DlPoint(size.width, 0),
137 DlPoint(0, 0), DlPoint(size.width, size.height),
138 };
139 std::vector<DlColor> colors = {
140 DlColor::kRed().modulateOpacity(0.5),
141 DlColor::kBlue().modulateOpacity(0.5),
142 DlColor::kGreen().modulateOpacity(0.5),
143 DlColor::kRed().modulateOpacity(0.5),
144 DlColor::kBlue().modulateOpacity(0.5),
145 DlColor::kGreen().modulateOpacity(0.5),
146 };
147
148 auto vertices =
149 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
150
151 builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
153 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [277/494]

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(
56 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
57
58 std::vector<DlPoint> vertex_coordinates = {
59 DlPoint(0, 0),
60 DlPoint(size.width, 0),
61 DlPoint(0, size.height),
62 };
63 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
64 {0, 1, 2}, {}, {});
65
66 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
67 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
68 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [278/494]

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

Definition at line 71 of file aiks_dl_vertices_unittests.cc.

71 {
72 DisplayListBuilder builder;
73 DlPaint paint;
74 auto image =
75 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
76 auto size = image->impeller_texture()->GetSize();
77
78 DlMatrix matrix = DlMatrix::MakeTranslation({100, 100});
79 paint.setColorSource(
80 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp,
81 DlImageSampling::kLinear, &matrix));
82
83 std::vector<DlPoint> positions = {
84 DlPoint(0, 0),
85 DlPoint(size.width, 0),
86 DlPoint(0, size.height),
87 };
88 auto vertices =
89 MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
90
91 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [279/494]

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() [280/494]

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.GetRange().offset, 4u);
58 EXPECT_EQ(buffer_view.GetRange().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() [281/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentPixelFormatsFails |
| ) |  |

Definition at line 30 of file blit_pass_unittests.cc.

30 {
31 ScopedValidationDisable scope; // avoid noise in output.
32 auto context = GetContext();
33 auto cmd_buffer = context->CreateCommandBuffer();
34 auto blit_pass = cmd_buffer->CreateBlitPass();
35
36 TextureDescriptor src_desc;
37 src_desc.format = PixelFormat::kA8UNormInt;
38 src_desc.size = {100, 100};
39 src_desc.storage_mode = StorageMode::kHostVisible;
40 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
41
42 TextureDescriptor dst_format;
43 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
44 dst_format.size = {100, 100};
45 dst_format.storage_mode = StorageMode::kHostVisible;
46 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
47
48 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
49 }

References impeller::TextureDescriptor::format, impeller::kA8UNormInt, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [282/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentSampleCountsFails |
| ) |  |

Definition at line 51 of file blit_pass_unittests.cc.

51 {
52 ScopedValidationDisable scope; // avoid noise in output.
53 auto context = GetContext();
54 auto cmd_buffer = context->CreateCommandBuffer();
55 auto blit_pass = cmd_buffer->CreateBlitPass();
56
57 TextureDescriptor src_desc;
58 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
59 src_desc.sample_count = SampleCount::kCount4;
60 src_desc.size = {100, 100};
61 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
62
63 TextureDescriptor dst_format;
64 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
65 dst_format.size = {100, 100};
66 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
67
68 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
69 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::sample_count, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [283/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitPassesForMatchingFormats |
| ) |  |

Definition at line 71 of file blit_pass_unittests.cc.

71 {
72 ScopedValidationDisable scope; // avoid noise in output.
73 auto context = GetContext();
74 auto cmd_buffer = context->CreateCommandBuffer();
75 auto blit_pass = cmd_buffer->CreateBlitPass();
76
77 TextureDescriptor src_desc;
78 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
79 src_desc.size = {100, 100};
80 src_desc.storage_mode = StorageMode::kHostVisible;
81 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
82
83 TextureDescriptor dst_format;
84 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
85 dst_format.size = {100, 100};
86 dst_format.storage_mode = StorageMode::kHostVisible;
87 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
88
89 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
90 }

References impeller::TextureDescriptor::format, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [284/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanBlitSmallRegionToUninitializedTexture |
| ) |  |

Definition at line 123 of file blit_pass_unittests.cc.

123 {
124 auto context = GetContext();
125 auto cmd_buffer = context->CreateCommandBuffer();
126 auto blit_pass = cmd_buffer->CreateBlitPass();
127
128 TextureDescriptor dst_format;
129 dst_format.storage_mode = StorageMode::kDevicePrivate;
130 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
131 dst_format.size = {1000, 1000};
132 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
133
134 DeviceBufferDescriptor src_format;
135 src_format.size = 4;
136 src_format.storage_mode = StorageMode::kHostVisible;
137 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
138
139 ASSERT_TRUE(dst);
140
141 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
142 IRect::MakeLTRB(0, 0, 1, 1), "",
143 /*mip_level=*/0, /*slice=*/0));
144 EXPECT_TRUE(blit_pass->EncodeCommands());
145 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
146 }

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() [285/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanBlitToHigherTextureMipLevels |
| ) |  |

Definition at line 176 of file blit_pass_unittests.cc.

176 {
177 auto context = GetContext();
178 auto cmd_buffer = context->CreateCommandBuffer();
179 auto blit_pass = cmd_buffer->CreateBlitPass();
180
181 TextureDescriptor dst_format;
182 dst_format.storage_mode = StorageMode::kDevicePrivate;
183 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
184 dst_format.size = {1000, 1000};
185 dst_format.mip_count = 4;
186 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
187
188 DeviceBufferDescriptor src_format;
189 src_format.size = 4;
190 src_format.storage_mode = StorageMode::kHostVisible;
191 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
192
193 ASSERT_TRUE(dst);
194
195 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
196 IRect::MakeLTRB(0, 0, 1, 1), "",
197 /*mip_level=*/1, /*slice=*/0));
198 EXPECT_TRUE(blit_pass->EncodeCommands());
199 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
200 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TRect< T >::MakeLTRB(), impeller::TextureDescriptor::mip_count, impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [286/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanResizeTextures |
| ) |  |

Definition at line 202 of file blit_pass_unittests.cc.

202 {
203 auto context = GetContext();
204 auto cmd_buffer = context->CreateCommandBuffer();
205 auto blit_pass = cmd_buffer->CreateBlitPass();
206
207 TextureDescriptor dst_format;
208 dst_format.storage_mode = StorageMode::kDevicePrivate;
209 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
210 dst_format.size = {10, 10};
211 dst_format.usage = TextureUsage::kShaderRead | TextureUsage::kShaderWrite;
212 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
213
214 TextureDescriptor src_format;
215 src_format.storage_mode = StorageMode::kDevicePrivate;
216 src_format.format = PixelFormat::kR8G8B8A8UNormInt;
217 src_format.size = {100, 100};
218 auto src = context->GetResourceAllocator()->CreateTexture(src_format);
219
220 std::vector<uint8_t> bytes(src_format.GetByteSizeOfBaseMipLevel());
221 for (auto i = 0u; i < src_format.GetByteSizeOfBaseMipLevel(); i += 4) {
222 // RGBA
223 bytes[i + 0] = 255;
224 bytes[i + 1] = 0;
225 bytes[i + 2] = 0;
226 bytes[i + 3] = 255;
227 }
228 auto mapping = fml::DataMapping(bytes);
229 auto staging = context->GetResourceAllocator()->CreateBufferWithCopy(mapping);
230
231 ASSERT_TRUE(dst);
232 ASSERT_TRUE(src);
233 ASSERT_TRUE(staging);
234
235 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(staging), src));
236 EXPECT_TRUE(blit_pass->ResizeTexture(src, dst));
237 EXPECT_TRUE(blit_pass->EncodeCommands());
238 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
239 }

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

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanResizeTexturesPlayground |
| ) |  |

Definition at line 241 of file blit_pass_unittests.cc.

241 {
242 auto context = GetContext();
243 auto cmd_buffer = context->CreateCommandBuffer();
244 auto blit_pass = cmd_buffer->CreateBlitPass();
245
246 std::shared_ptr<Texture> src = CreateTextureForFixture("kalimba.jpg");
247
248 TextureDescriptor dst_format;
249 dst_format.storage_mode = StorageMode::kDevicePrivate;
250 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
251 dst_format.size = {src->GetSize().width / 2, src->GetSize().height};
252 dst_format.usage = TextureUsage::kShaderRead | TextureUsage::kShaderWrite;
253 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
254
255 ASSERT_TRUE(dst);
256 ASSERT_TRUE(src);
257
258 EXPECT_TRUE(blit_pass->ResizeTexture(src, dst));
259 EXPECT_TRUE(blit_pass->EncodeCommands());
260 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
261
262 DisplayListBuilder builder;
263 builder.Scale(GetContentScale().x, GetContentScale().y);
264 DlPaint paint;
265 paint.setColor(DlColor::kRed());
266 auto image = DlImageImpeller::Make(dst);
267 builder.DrawImage(image, SkPoint::Make(100.0, 100.0),
268 DlImageSampling::kNearestNeighbor, &paint);
269 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
270 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kR8G8B8A8UNormInt, impeller::kShaderRead, impeller::kShaderWrite, impeller::DlImageImpeller::Make(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::TextureDescriptor::usage, impeller::TSize< T >::width, and x.

## ◆ TEST_P() [288/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | ChecksInvalidMipLevelParameter |
| ) |  |

Definition at line 148 of file blit_pass_unittests.cc.

148 {
149 ScopedValidationDisable scope;
150 auto context = GetContext();
151 auto cmd_buffer = context->CreateCommandBuffer();
152 auto blit_pass = cmd_buffer->CreateBlitPass();
153
154 TextureDescriptor dst_format;
155 dst_format.storage_mode = StorageMode::kDevicePrivate;
156 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
157 dst_format.size = {1000, 1000};
158 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
159
160 DeviceBufferDescriptor src_format;
161 src_format.size = 4;
162 src_format.storage_mode = StorageMode::kHostVisible;
163 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
164
165 ASSERT_TRUE(dst);
166
167 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
168 IRect::MakeLTRB(0, 0, 1, 1), "",
169 /*mip_level=*/1, /*slice=*/0));
170
171 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
172 IRect::MakeLTRB(0, 0, 1, 1), "",
173 /*mip_level=*/0, /*slice=*/0));
174 }

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() [289/494]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | ChecksInvalidSliceParameters |
| ) |  |

Definition at line 92 of file blit_pass_unittests.cc.

92 {
93 ScopedValidationDisable scope; // avoid noise in output.
94 auto context = GetContext();
95 auto cmd_buffer = context->CreateCommandBuffer();
96 auto blit_pass = cmd_buffer->CreateBlitPass();
97
98 TextureDescriptor dst_format;
99 dst_format.storage_mode = StorageMode::kDevicePrivate;
100 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
101 dst_format.size = {100, 100};
102 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
103
104 DeviceBufferDescriptor src_format;
105 src_format.size = 40000;
106 src_format.storage_mode = StorageMode::kHostVisible;
107 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
108
109 ASSERT_TRUE(dst);
110 ASSERT_TRUE(src);
111
112 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
113 std::nullopt, "", /*mip_level=*/0,
114 /*slice=*/25));
115 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
116 std::nullopt, "", /*mip_level=*/0,
117 /*slice=*/6));
118 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
119 std::nullopt, "", /*mip_level=*/0,
120 /*slice=*/0));
121 }

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

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | 1DThreadgroupSizingIsCorrect |
| ) |  |

Definition at line 177 of file compute_unittests.cc.

177 {
178 using CS = ThreadgroupSizingTestComputeShader;
179 auto context = GetContext();
180 ASSERT_TRUE(context);
181 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
182
183 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
184 auto pipeline_desc =
185 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
186 ASSERT_TRUE(pipeline_desc.has_value());
187 auto compute_pipeline =
188 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
189 ASSERT_TRUE(compute_pipeline);
190
191 auto cmd_buffer = context->CreateCommandBuffer();
192 auto pass = cmd_buffer->CreateComputePass();
193 ASSERT_TRUE(pass && pass->IsValid());
194
195 static constexpr size_t kCount = 2048;
196
197 pass->SetPipeline(compute_pipeline);
198
199 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
200 context, "Output Buffer");
201
202 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
203
204 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
205 ASSERT_TRUE(pass->EncodeCommands());
206
207 fml::AutoResetWaitableEvent latch;
208 ASSERT_TRUE(
209 context->GetCommandQueue()
210 ->Submit({cmd_buffer},
211 [&latch, output_buffer](CommandBuffer::Status status) {
212 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
213
214 auto view = DeviceBuffer::AsBufferView(output_buffer);
215 EXPECT_EQ(view.GetRange().length,
216 sizeof(CS::OutputData<kCount>));
217
218 CS::OutputData<kCount>* output =
219 reinterpret_cast<CS::OutputData<kCount>*>(
220 output_buffer->OnGetContents());
221 EXPECT_TRUE(output);
222 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
223 latch.Signal();
224 })
225 .ok());
226
227 latch.Wait();
228 }

## ◆ TEST_P() [291/494]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCompute1DimensionalData |
| ) |  |

Definition at line 377 of file compute_unittests.cc.

377 {
378 using CS = SampleComputeShader;
379 auto context = GetContext();
380 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
381 context->GetIdleWaiter());
382 ASSERT_TRUE(context);
383 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
384
385 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
386 auto pipeline_desc =
387 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
388 ASSERT_TRUE(pipeline_desc.has_value());
389 auto compute_pipeline =
390 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
391 ASSERT_TRUE(compute_pipeline);
392
393 auto cmd_buffer = context->CreateCommandBuffer();
394 auto pass = cmd_buffer->CreateComputePass();
395 ASSERT_TRUE(pass && pass->IsValid());
396
397 static constexpr size_t kCount = 5;
398
399 pass->SetPipeline(compute_pipeline);
400
401 CS::Info info{.count = kCount};
402 CS::Input0<kCount> input_0;
403 CS::Input1<kCount> input_1;
404 for (size_t i = 0; i < kCount; i++) {
405 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
406 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
407 }
408
409 input_0.fixed_array[1] = IPoint32(2, 2);
410 input_1.fixed_array[0] = UintPoint32(3, 3);
411 input_0.some_int = 5;
412 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
413
414 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
415 context, "Output Buffer");
416
417 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
418 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
419 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
420 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
421
422 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
423 ASSERT_TRUE(pass->EncodeCommands());
424
425 fml::AutoResetWaitableEvent latch;
426 ASSERT_TRUE(
427 context->GetCommandQueue()
428 ->Submit(
429 {cmd_buffer},
430 [&latch, output_buffer, &input_0,
431 &input_1](CommandBuffer::Status status) {
432 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
433
434 auto view = DeviceBuffer::AsBufferView(output_buffer);
435 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
436
437 CS::Output<kCount>* output =
438 reinterpret_cast<CS::Output<kCount>*>(
439 output_buffer->OnGetContents());
440 EXPECT_TRUE(output);
441 for (size_t i = 0; i < kCount; i++) {
442 Vector4 vector = output->elements[i];
443 Vector4 computed = input_0.elements[i] * input_1.elements[i];
444 EXPECT_EQ(vector,
445 Vector4(computed.x + 2 + input_1.some_struct.i,
446 computed.y + 3 + input_1.some_struct.vf.x,
447 computed.z + 5 + input_1.some_struct.vf.y,
448 computed.w));
449 }
450 latch.Signal();
451 })
452 .ok());
453
454 latch.Wait();
455 }

References impeller::interop::Create().

## ◆ TEST_P() [292/494]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSum |
| ) |  |

Definition at line 110 of file compute_unittests.cc.

110 {
111 using CS = PrefixSumTestComputeShader;
112 auto context = GetContext();
113 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
114 context->GetIdleWaiter());
115 ASSERT_TRUE(context);
116 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
117
118 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
119 auto pipeline_desc =
120 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
121 ASSERT_TRUE(pipeline_desc.has_value());
122 auto compute_pipeline =
123 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
124 ASSERT_TRUE(compute_pipeline);
125
126 auto cmd_buffer = context->CreateCommandBuffer();
127 auto pass = cmd_buffer->CreateComputePass();
128 ASSERT_TRUE(pass && pass->IsValid());
129
130 static constexpr size_t kCount = 5;
131
132 pass->SetPipeline(compute_pipeline);
133
134 CS::InputData<kCount> input_data;
135 input_data.count = kCount;
136 for (size_t i = 0; i < kCount; i++) {
137 input_data.data[i] = 1 + i;
138 }
139
140 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
141 context, "Output Buffer");
142
143 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
144 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
145
146 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
147 ASSERT_TRUE(pass->EncodeCommands());
148
149 fml::AutoResetWaitableEvent latch;
150 ASSERT_TRUE(
151 context->GetCommandQueue()
152 ->Submit({cmd_buffer},
153 [&latch, output_buffer](CommandBuffer::Status status) {
154 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
155
156 auto view = DeviceBuffer::AsBufferView(output_buffer);
157 EXPECT_EQ(view.GetRange().length,
158 sizeof(CS::OutputData<kCount>));
159
160 CS::OutputData<kCount>* output =
161 reinterpret_cast<CS::OutputData<kCount>*>(
162 output_buffer->OnGetContents());
163 EXPECT_TRUE(output);
164
165 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
166 for (size_t i = 0; i < kCount; i++) {
167 auto computed_sum = output->data[i];
168 EXPECT_EQ(computed_sum, expected[i]);
169 }
170 latch.Signal();
171 })
172 .ok());
173
174 latch.Wait();
175 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [293/494]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSumLargeInteractive |
| ) |  |

Definition at line 230 of file compute_unittests.cc.

230 {
231 using CS = PrefixSumTestComputeShader;
232
233 auto context = GetContext();
234 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
235 context->GetIdleWaiter());
236
237 ASSERT_TRUE(context);
238 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
239
240 auto callback = [&](RenderPass& render_pass) -> bool {
241 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
242 auto pipeline_desc =
243 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
244 auto compute_pipeline =
245 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
246
247 auto cmd_buffer = context->CreateCommandBuffer();
248 auto pass = cmd_buffer->CreateComputePass();
249
250 static constexpr size_t kCount = 1023;
251
252 pass->SetPipeline(compute_pipeline);
253
254 CS::InputData<kCount> input_data;
255 input_data.count = kCount;
256 for (size_t i = 0; i < kCount; i++) {
257 input_data.data[i] = 1 + i;
258 }
259
260 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
261 context, "Output Buffer");
262
263 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
264 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
265
266 pass->Compute(ISize(kCount, 1));
267 pass->EncodeCommands();
268 host_buffer->Reset();
269 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
270 };
271 ASSERT_TRUE(OpenPlaygroundHere(callback));
272 }

References impeller::interop::Create().

## ◆ TEST_P() [294/494]

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 context->GetIdleWaiter());
35 ASSERT_TRUE(context);
36 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
37
38 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
39 auto pipeline_desc =
40 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
41 ASSERT_TRUE(pipeline_desc.has_value());
42 auto compute_pipeline =
43 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
44 ASSERT_TRUE(compute_pipeline);
45
46 auto cmd_buffer = context->CreateCommandBuffer();
47 auto pass = cmd_buffer->CreateComputePass();
48 ASSERT_TRUE(pass && pass->IsValid());
49
50 static constexpr size_t kCount = 5;
51
52 pass->SetPipeline(compute_pipeline);
53
54 CS::Info info{.count = kCount};
55 CS::Input0<kCount> input_0;
56 CS::Input1<kCount> input_1;
57 for (size_t i = 0; i < kCount; i++) {
58 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
59 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
60 }
61
62 input_0.fixed_array[1] = IPoint32(2, 2);
63 input_1.fixed_array[0] = UintPoint32(3, 3);
64 input_0.some_int = 5;
65 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
66
67 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
68 context, "Output Buffer");
69
70 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
71 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
72 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
73 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
74
75 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
76 ASSERT_TRUE(pass->EncodeCommands());
77
78 fml::AutoResetWaitableEvent latch;
79 ASSERT_TRUE(
80 context->GetCommandQueue()
81 ->Submit(
82 {cmd_buffer},
83 [&latch, output_buffer, &input_0,
84 &input_1](CommandBuffer::Status status) {
85 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
86
87 auto view = DeviceBuffer::AsBufferView(output_buffer);
88 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
89
90 CS::Output<kCount>* output =
91 reinterpret_cast<CS::Output<kCount>*>(
92 output_buffer->OnGetContents());
93 EXPECT_TRUE(output);
94 for (size_t i = 0; i < kCount; i++) {
95 Vector4 vector = output->elements[i];
96 Vector4 computed = input_0.elements[i] * input_1.elements[i];
97 EXPECT_EQ(vector,
98 Vector4(computed.x + 2 + input_1.some_struct.i,
99 computed.y + 3 + input_1.some_struct.vf.x,
100 computed.z + 5 + input_1.some_struct.vf.y,
101 computed.w));
102 }
103 latch.Signal();
104 })
105 .ok());
106
107 latch.Wait();
108 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [295/494]

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() [296/494]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | MultiStageInputAndOutput |
| ) |  |

Definition at line 274 of file compute_unittests.cc.

274 {
275 using CS1 = Stage1ComputeShader;
276 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
277 using CS2 = Stage2ComputeShader;
278 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
279
280 auto context = GetContext();
281 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
282 context->GetIdleWaiter());
283 ASSERT_TRUE(context);
284 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
285
286 auto pipeline_desc_1 =
287 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
288 ASSERT_TRUE(pipeline_desc_1.has_value());
289 auto compute_pipeline_1 =
290 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
291 ASSERT_TRUE(compute_pipeline_1);
292
293 auto pipeline_desc_2 =
294 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
295 ASSERT_TRUE(pipeline_desc_2.has_value());
296 auto compute_pipeline_2 =
297 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
298 ASSERT_TRUE(compute_pipeline_2);
299
300 auto cmd_buffer = context->CreateCommandBuffer();
301 auto pass = cmd_buffer->CreateComputePass();
302 ASSERT_TRUE(pass && pass->IsValid());
303
304 static constexpr size_t kCount1 = 5;
305 static constexpr size_t kCount2 = kCount1 * 2;
306
307 CS1::Input<kCount1> input_1;
308 input_1.count = kCount1;
309 for (size_t i = 0; i < kCount1; i++) {
310 input_1.elements[i] = i;
311 }
312
313 CS2::Input<kCount2> input_2;
314 input_2.count = kCount2;
315 for (size_t i = 0; i < kCount2; i++) {
316 input_2.elements[i] = i;
317 }
318
319 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
320 context, "Output Buffer Stage 1");
321 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
322 context, "Output Buffer Stage 2");
323
324 {
325 pass->SetPipeline(compute_pipeline_1);
326
327 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
328 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
329
330 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
331 pass->AddBufferMemoryBarrier();
332 }
333
334 {
335 pass->SetPipeline(compute_pipeline_2);
336
337 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
338 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
339 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
340 }
341
342 ASSERT_TRUE(pass->EncodeCommands());
343
344 fml::AutoResetWaitableEvent latch;
345 ASSERT_TRUE(
346 context->GetCommandQueue()
347 ->Submit({cmd_buffer},
348 [&latch, &output_buffer_1,
349 &output_buffer_2](CommandBuffer::Status status) {
350 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
351
352 CS1::Output<kCount2>* output_1 =
353 reinterpret_cast<CS1::Output<kCount2>*>(
354 output_buffer_1->OnGetContents());
355 EXPECT_TRUE(output_1);
356 EXPECT_EQ(output_1->count, 10u);
357 EXPECT_THAT(
358 output_1->elements,
359 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
360
361 CS2::Output<kCount2>* output_2 =
362 reinterpret_cast<CS2::Output<kCount2>*>(
363 output_buffer_2->OnGetContents());
364 EXPECT_TRUE(output_2);
365 EXPECT_EQ(output_2->count, 10u);
366 EXPECT_THAT(output_2->elements,
367 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
368 18, 16, 24));
369
370 latch.Signal();
371 })
372 .ok());
373
374 latch.Wait();
375 }

References impeller::interop::Create(), and impeller::kCount1.

## ◆ TEST_P() [297/494]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | ReturnsEarlyWhenAnyGridDimensionIsZero |
| ) |  |

Definition at line 457 of file compute_unittests.cc.

457 {
458 using CS = SampleComputeShader;
459 auto context = GetContext();
460 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
461 context->GetIdleWaiter());
462 ASSERT_TRUE(context);
463 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
464
465 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
466 auto pipeline_desc =
467 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
468 ASSERT_TRUE(pipeline_desc.has_value());
469 auto compute_pipeline =
470 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
471 ASSERT_TRUE(compute_pipeline);
472
473 auto cmd_buffer = context->CreateCommandBuffer();
474 auto pass = cmd_buffer->CreateComputePass();
475 ASSERT_TRUE(pass && pass->IsValid());
476
477 static constexpr size_t kCount = 5;
478
479 pass->SetPipeline(compute_pipeline);
480
481 CS::Info info{.count = kCount};
482 CS::Input0<kCount> input_0;
483 CS::Input1<kCount> input_1;
484 for (size_t i = 0; i < kCount; i++) {
485 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
486 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
487 }
488
489 input_0.fixed_array[1] = IPoint32(2, 2);
490 input_1.fixed_array[0] = UintPoint32(3, 3);
491 input_0.some_int = 5;
492 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
493
494 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
495 context, "Output Buffer");
496
497 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
498 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
499 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
500 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
501
502 // Intentionally making the grid size zero in one dimension. No GPU will
503 // tolerate this.
504 EXPECT_FALSE(pass->Compute(ISize(0, 1)).ok());
505 pass->EncodeCommands();
506 }

References impeller::interop::Create().

## ◆ TEST_P() [298/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1170 of file dl_unittests.cc.

1170 {
1171 flutter::DisplayListBuilder builder;
1172
1173 {
1174 builder.SaveLayer(nullptr, nullptr);
1175 builder.Translate(100, 100);
1176 flutter::DlPaint paint;
1177 paint.setColor(flutter::DlColor::kRed());
1178 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1179 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1180 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1181 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1182 builder.Restore();
1183 }
1184 {
1185 builder.SaveLayer(nullptr, nullptr);
1186 builder.Translate(300, 100);
1187 flutter::DlPaint paint;
1188 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1189 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1190 paint.setColor(flutter::DlColor::kRed());
1191 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1192 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1193 builder.Restore();
1194 }
1195 {
1196 builder.SaveLayer(nullptr, nullptr);
1197 builder.Translate(100, 300);
1198 flutter::DlPaint paint;
1199 paint.setColor(flutter::DlColor::kRed());
1200 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1201 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1202 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1203 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1204 builder.Restore();
1205 }
1206 {
1207 builder.SaveLayer(nullptr, nullptr);
1208 builder.Translate(300, 300);
1209 flutter::DlPaint paint;
1210 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1211 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1212 paint.setColor(flutter::DlColor::kRed());
1213 paint.setBlendMode(flutter::DlBlendMode::kDst);
1214 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1215 builder.Restore();
1216 }
1217
1218 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1219 }

## ◆ TEST_P() [299/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 614 of file dl_unittests.cc.

614 {
615 auto texture = CreateTextureForFixture("boston.jpg");
616 const float inner_color_matrix[20] = {
617 1, 0, 0, 0, 0, //
618 0, 1, 0, 0, 0, //
619 0, 0, 1, 0, 0, //
620 0, 0, 0, 2, 0, //
621 };
622 const float outer_color_matrix[20] = {
623 1, 0, 0, 0, 0, //
624 0, 1, 0, 0, 0, //
625 0, 0, 1, 0, 0, //
626 0, 0, 0, 0.5, 0, //
627 };
628 auto inner_color_filter =
629 flutter::DlColorFilter::MakeMatrix(inner_color_matrix);
630 auto outer_color_filter =
631 flutter::DlColorFilter::MakeMatrix(outer_color_matrix);
632 auto inner = flutter::DlImageFilter::MakeColorFilter(inner_color_filter);
633 auto outer = flutter::DlImageFilter::MakeColorFilter(outer_color_filter);
634 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
635
636 flutter::DisplayListBuilder builder;
637 flutter::DlPaint paint;
638 paint.setImageFilter(compose.get());
639 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
640 flutter::DlImageSampling::kNearestNeighbor, &paint);
641 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
642 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [300/494]

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

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() [302/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 644 of file dl_unittests.cc.

644 {
645 auto texture = CreateTextureForFixture("embarcadero.jpg");
646
647 auto callback = [&]() {
648 static float sigma[] = {10, 10};
649 static float ctm_scale = 1;
650 static bool use_bounds = true;
651 static bool draw_circle = true;
652 static bool add_clip = true;
653
654 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
655 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
656 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
657 ImGui::NewLine();
658 ImGui::TextWrapped(
659 "If everything is working correctly, none of the options below should "
660 "impact the filter's appearance.");
661 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
662 ImGui::Checkbox("Draw child element", &draw_circle);
663 ImGui::Checkbox("Add pre-clip", &add_clip);
664 ImGui::End();
665
666 flutter::DisplayListBuilder builder;
667
668 Vector2 scale = ctm_scale * GetContentScale();
669 builder.Scale(scale.x, scale.y);
670
671 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
672 flutter::DlTileMode::kClamp);
673
674 std::optional<SkRect> bounds;
675 if (use_bounds) {
676 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
677 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
678 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
679 bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
680 }
681
682 // Insert a clip to test that the backdrop filter handles stencil depths > 0
683 // correctly.
684 if (add_clip) {
685 builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
686 flutter::DlCanvas::ClipOp::kIntersect, true);
687 }
688
689 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
690 flutter::DlImageSampling::kNearestNeighbor, nullptr);
691 builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
692 &filter);
693
694 if (draw_circle) {
695 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
696 auto circle_center = DrawPlaygroundPoint(center_point);
697
698 flutter::DlPaint paint;
699 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
700 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
701 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
702 paint.setStrokeWidth(10);
703 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
704 builder.DrawCircle(SkPoint{circle_center.x, circle_center.y}, 100, paint);
705 }
706
707 return builder.Build();
708 };
709
710 ASSERT_TRUE(OpenPlaygroundHere(callback));
711 }

References impeller::DrawPlaygroundLine(), impeller::DrawPlaygroundPoint(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), scale, and impeller::Color::White().

## ◆ TEST_P() [303/494]

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() [304/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1221 of file dl_unittests.cc.

1221 {
1222 flutter::DisplayListBuilder builder;
1223 const float green_color_matrix[20] = {
1224 0, 0, 0, 0, 0, //
1225 0, 0, 0, 0, 1, //
1226 0, 0, 0, 0, 0, //
1227 0, 0, 0, 1, 0, //
1228 };
1229 const float blue_color_matrix[20] = {
1230 0, 0, 0, 0, 0, //
1231 0, 0, 0, 0, 0, //
1232 0, 0, 0, 0, 1, //
1233 0, 0, 0, 1, 0, //
1234 };
1235 auto green_color_filter =
1236 flutter::DlColorFilter::MakeMatrix(green_color_matrix);
1237 auto blue_color_filter =
1238 flutter::DlColorFilter::MakeMatrix(blue_color_matrix);
1239 auto blue_image_filter =
1240 flutter::DlImageFilter::MakeColorFilter(blue_color_filter);
1241
1242 flutter::DlPaint paint;
1243 paint.setColor(flutter::DlColor::kRed());
1244 paint.setColorFilter(green_color_filter);
1245 paint.setImageFilter(blue_image_filter);
1246 builder.DrawRect(SkRect::MakeLTRB(100, 100, 500, 500), paint);
1247 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1248 }

## ◆ TEST_P() [305/494]

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() [306/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 713 of file dl_unittests.cc.

713 {
714 // Image is drawn with corners to scale and center pieces stretched to fit.
715 auto texture = CreateTextureForFixture("embarcadero.jpg");
716 flutter::DisplayListBuilder builder;
717 auto size = texture->GetSize();
718 builder.DrawImageNine(
719 DlImageImpeller::Make(texture),
720 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
721 size.height * 3 / 4),
722 SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
723 flutter::DlFilterMode::kNearest, nullptr);
724 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
725 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [307/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 759 of file dl_unittests.cc.

759 {
760 // Edge case, the width and height of the corners does not leave any
761 // room for the center slices. Only the corners are displayed.
762 auto texture = CreateTextureForFixture("embarcadero.jpg");
763 flutter::DisplayListBuilder builder;
764 auto size = texture->GetSize();
765 builder.DrawImageNine(
766 DlImageImpeller::Make(texture),
767 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
768 size.height * 3 / 4),
769 SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
770 flutter::DlFilterMode::kNearest, nullptr);
771 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
772 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [308/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 743 of file dl_unittests.cc.

743 {
744 // Edge case, the height of the corners does not leave any room for the
745 // center slice. The center (across the horizontal axis) is folded out of the
746 // resulting image.
747 auto texture = CreateTextureForFixture("embarcadero.jpg");
748 flutter::DisplayListBuilder builder;
749 auto size = texture->GetSize();
750 builder.DrawImageNine(
751 DlImageImpeller::Make(texture),
752 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
753 size.height * 3 / 4),
754 SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
755 flutter::DlFilterMode::kNearest, nullptr);
756 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
757 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [309/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 727 of file dl_unittests.cc.

727 {
728 // Edge case, the width of the corners does not leave any room for the
729 // center slice. The center (across the vertical axis) is folded out of the
730 // resulting image.
731 auto texture = CreateTextureForFixture("embarcadero.jpg");
732 flutter::DisplayListBuilder builder;
733 auto size = texture->GetSize();
734 builder.DrawImageNine(
735 DlImageImpeller::Make(texture),
736 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
737 size.height * 3 / 4),
738 SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
739 flutter::DlFilterMode::kNearest, nullptr);
740 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
741 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [310/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 774 of file dl_unittests.cc.

774 {
775 // Edge case, there is not enough room for the corners to be drawn
776 // without scaling them down.
777 auto texture = CreateTextureForFixture("embarcadero.jpg");
778 flutter::DisplayListBuilder builder;
779 auto size = texture->GetSize();
780 builder.DrawImageNine(
781 DlImageImpeller::Make(texture),
782 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
783 size.height * 3 / 4),
784 SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
785 flutter::DlFilterMode::kNearest, nullptr);
786 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
787 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [311/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1118 of file dl_unittests.cc.

1118 {
1119 const flutter::DlColor colors[2] = {
1120 flutter::DlColor(0xFFF44336),
1121 flutter::DlColor(0xFF2196F3),
1122 };
1123 const float stops[2] = {0.0, 1.0};
1124 flutter::DlPaint paint;
1125 flutter::DisplayListBuilder builder;
1126 auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
1127 builder.Save();
1128 builder.Translate(100, 100);
1129 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1130 auto linear =
1131 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1132 stops, flutter::DlTileMode::kRepeat);
1133 paint.setColorSource(linear);
1134 builder.DrawPaint(paint);
1135 builder.Restore();
1136
1137 builder.Save();
1138 builder.Translate(500, 100);
1139 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1140 auto radial = flutter::DlColorSource::MakeRadial(
1141 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1142 paint.setColorSource(radial);
1143 builder.DrawPaint(paint);
1144 builder.Restore();
1145
1146 builder.Save();
1147 builder.Translate(100, 500);
1148 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1149 auto sweep =
1150 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1151 stops, flutter::DlTileMode::kRepeat);
1152 paint.setColorSource(sweep);
1153 builder.DrawPaint(paint);
1154 builder.Restore();
1155
1156 builder.Save();
1157 builder.Translate(500, 500);
1158 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1159 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1160 auto image = flutter::DlColorSource::MakeImage(DlImageImpeller::Make(texture),
1161 flutter::DlTileMode::kRepeat,
1162 flutter::DlTileMode::kRepeat);
1163 paint.setColorSource(image);
1164 builder.DrawPaint(paint);
1165 builder.Restore();
1166
1167 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1168 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [312/494]

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

Definition at line 801 of file dl_unittests.cc.

801 {
802 flutter::DisplayListBuilder builder;
803 SkPoint points[7] = {
804 {0, 0}, //
805 {100, 100}, //
806 {100, 0}, //
807 {0, 100}, //
808 {0, 0}, //
809 {48, 48}, //
810 {52, 52}, //
811 };
812 std::vector<flutter::DlStrokeCap> caps = {
813 flutter::DlStrokeCap::kButt,
814 flutter::DlStrokeCap::kRound,
815 flutter::DlStrokeCap::kSquare,
816 };
817 flutter::DlPaint paint =
818 flutter::DlPaint() //
819 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
820 .setStrokeWidth(20);
821 builder.Translate(50, 50);
822 for (auto cap : caps) {
823 paint.setStrokeCap(cap);
824 builder.Save();
825 builder.DrawPoints(flutter::DlCanvas::PointMode::kPoints, 7, points, paint);
826 builder.Translate(150, 0);
827 builder.DrawPoints(flutter::DlCanvas::PointMode::kLines, 5, points, paint);
828 builder.Translate(150, 0);
829 builder.DrawPoints(flutter::DlCanvas::PointMode::kPolygon, 5, points,
830 paint);
831 builder.Restore();
832 builder.Translate(0, 150);
833 }
834 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
835 }

## ◆ TEST_P() [313/494]

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() [314/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1104 of file dl_unittests.cc.

1104 {
1105 flutter::DlPaint paint;
1106 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1107 flutter::DisplayListBuilder builder;
1108 paint.setColorFilter(flutter::DlColorFilter::MakeLinearToSrgbGamma());
1109 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1110 builder.Translate(0, 200);
1111
1112 paint.setColorFilter(flutter::DlColorFilter::MakeSrgbToLinearGamma());
1113 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1114
1115 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1116 }

## ◆ TEST_P() [315/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 860 of file dl_unittests.cc.

860 {
861 flutter::DisplayListBuilder builder;
862 flutter::DlPaint paint;
863
864 auto content_scale = GetContentScale() * 0.8;
865 builder.Scale(content_scale.x, content_scale.y);
866
867 constexpr size_t star_spikes = 5;
868 constexpr SkScalar half_spike_rotation = kPi / star_spikes;
869 constexpr SkScalar radius = 40;
870 constexpr SkScalar spike_size = 10;
871 constexpr SkScalar outer_radius = radius + spike_size;
872 constexpr SkScalar inner_radius = radius - spike_size;
873 std::array<SkPoint, star_spikes * 2> star;
874 for (size_t i = 0; i < star_spikes; i++) {
875 const SkScalar rotation = half_spike_rotation * i * 2;
876 star[i * 2] = SkPoint::Make(50 + std::sin(rotation) * outer_radius,
877 50 - std::cos(rotation) * outer_radius);
878 star[i * 2 + 1] = SkPoint::Make(
879 50 + std::sin(rotation + half_spike_rotation) * inner_radius,
880 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
881 }
882
883 std::array<SkPath, 4> paths = {
884 SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
885 SkPath{}.addRRect(
886 SkRRect::MakeRectXY(SkRect::MakeXYWH(20, 0, 200, 100), 30, 30)),
887 SkPath{}.addCircle(100, 50, 50),
888 SkPath{}.addPoly(star.data(), star.size(), true),
889 };
890 paint.setColor(flutter::DlColor::kWhite());
891 builder.DrawPaint(paint);
892 paint.setColor(flutter::DlColor::kCyan());
893 builder.Translate(100, 50);
894 for (size_t x = 0; x < paths.size(); x++) {
895 builder.Save();
896 for (size_t y = 0; y < 6; y++) {
897 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
898 1);
899 builder.DrawPath(paths[x], paint);
900 builder.Translate(0, 150);
901 }
902 builder.Restore();
903 builder.Translate(250, 0);
904 }
905
906 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
907 }

References impeller::kPi, and x.

## ◆ TEST_P() [316/494]

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() [317/494]

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() [318/494]

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() [319/494]

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() [320/494]

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::DlColorFilter::MakeBlend(
526 flutter::DlColor::kYellow(), 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::DlColorFilter::MakeBlend(
535 flutter::DlColor::kRed(), 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() [321/494]

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 = flutter::DlColorFilter::MakeMatrix(invert_color_matrix);
556 auto image_filter = flutter::DlImageFilter::MakeColorFilter(color_filter);
557
558 paint.setImageFilter(image_filter);
559 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
560 flutter::DlImageSampling::kNearestNeighbor, &paint);
561
562 builder.Translate(0, 700);
563 paint.setColorFilter(color_filter);
564 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
565 flutter::DlImageSampling::kNearestNeighbor, &paint);
566 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
567 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [322/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 594 of file dl_unittests.cc.

594 {
595 auto texture = CreateTextureForFixture("boston.jpg");
596 flutter::DisplayListBuilder builder;
597 flutter::DlPaint paint;
598
599 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
600 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
601 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
602 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
603
604 paint.setImageFilter(open.get());
605 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
606 flutter::DlImageSampling::kNearestNeighbor, &paint);
607 builder.Translate(0, 700);
608 paint.setImageFilter(close.get());
609 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
610 flutter::DlImageSampling::kNearestNeighbor, &paint);
611 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
612 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [323/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 569 of file dl_unittests.cc.

569 {
570 auto texture = CreateTextureForFixture("embarcadero.jpg");
571
572 auto callback = [&]() {
573 static float sigma[] = {10, 10};
574
575 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
576 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
577 ImGui::End();
578
579 flutter::DisplayListBuilder builder;
580 flutter::DlPaint paint;
581
582 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
583 flutter::DlTileMode::kClamp);
584 paint.setImageFilter(&filter);
585 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
586 flutter::DlImageSampling::kNearestNeighbor, &paint);
587
588 return builder.Build();
589 };
590
591 ASSERT_TRUE(OpenPlaygroundHere(callback));
592 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [324/494]

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() [325/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 943 of file dl_unittests.cc.

943 {
944 auto boston = CreateTextureForFixture("boston.jpg");
945
946 auto callback = [&]() {
947 static int selected_matrix_type = 0;
948 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
949
950 static float ctm_translation[2] = {200, 200};
951 static float ctm_scale[2] = {0.65, 0.65};
952 static float ctm_skew[2] = {0, 0};
953
954 static bool enable = true;
955 static float translation[2] = {100, 100};
956 static float scale[2] = {0.8, 0.8};
957 static float skew[2] = {0.2, 0.2};
958
959 static bool enable_savelayer = true;
960
961 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
962 {
963 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
964 sizeof(matrix_type_names) / sizeof(char*));
965
966 ImGui::TextWrapped("Current Transform");
967 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
968 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
969 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
970
971 ImGui::TextWrapped(
972 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
973 "The only difference is that MatrixFilter doesn't affect the effect "
974 "transform, whereas LocalMatrixFilter does.");
975 // Note: See this behavior in:
976 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
977 ImGui::Checkbox("Enable", &enable);
978 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
979 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
980 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
981
982 ImGui::TextWrapped(
983 "Rendering the filtered image within a layer can expose bounds "
984 "issues. If the rendered image gets cut off when this setting is "
985 "enabled, there's a coverage bug in the filter.");
986 ImGui::Checkbox("Render in layer", &enable_savelayer);
987 }
988 ImGui::End();
989
990 flutter::DisplayListBuilder builder;
991 flutter::DlPaint paint;
992
993 if (enable_savelayer) {
994 builder.SaveLayer(nullptr, nullptr);
995 }
996 {
997 auto content_scale = GetContentScale();
998 builder.Scale(content_scale.x, content_scale.y);
999
1000 // Set the current transform
1001 auto ctm_matrix =
1002 SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
1003 ctm_skew[1], ctm_scale[1], ctm_translation[1], //
1004 0, 0, 1);
1005 builder.Transform(ctm_matrix);
1006
1007 // Set the matrix filter
1008 auto filter_matrix =
1009 Matrix::MakeRow(scale[0], skew[0], 0.0f, translation[0], //
1010 skew[1], scale[1], 0.0f, translation[1], //
1011 0.0f, 0.0f, 1.0f, 0.0f, //
1012 0.0f, 0.0f, 0.0f, 1.0f);
1013
1014 if (enable) {
1015 switch (selected_matrix_type) {
1016 case 0: {
1017 auto filter = flutter::DlMatrixImageFilter(
1018 filter_matrix, flutter::DlImageSampling::kLinear);
1019 paint.setImageFilter(&filter);
1020 break;
1021 }
1022 case 1: {
1023 auto internal_filter =
1024 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1025 .shared();
1026 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1027 internal_filter);
1028 paint.setImageFilter(&filter);
1029 break;
1030 }
1031 }
1032 }
1033
1034 builder.DrawImage(DlImageImpeller::Make(boston), SkPoint{},
1035 flutter::DlImageSampling::kLinear, &paint);
1036 }
1037 if (enable_savelayer) {
1038 builder.Restore();
1039 }
1040
1041 return builder.Build();
1042 };
1043
1044 ASSERT_TRUE(OpenPlaygroundHere(callback));
1045 }

References impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRow(), and scale.

## ◆ TEST_P() [326/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1047 of file dl_unittests.cc.

1047 {
1048 auto callback = [&]() {
1049 static float translation[2] = {0, 0};
1050 static bool enable_save_layer = true;
1051
1052 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1053 ImGui::SliderFloat2("Translation", translation, -130, 130);
1054 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1055 ImGui::End();
1056
1057 flutter::DisplayListBuilder builder;
1058 builder.Save();
1059 builder.Scale(2.0, 2.0);
1060 flutter::DlPaint paint;
1061 paint.setColor(flutter::DlColor::kYellow());
1062 builder.DrawRect(SkRect::MakeWH(300, 300), paint);
1063 paint.setStrokeWidth(1.0);
1064 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1065 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1066 builder.DrawLine(SkPoint::Make(150, 0), SkPoint::Make(150, 300), paint);
1067 builder.DrawLine(SkPoint::Make(0, 150), SkPoint::Make(300, 150), paint);
1068
1069 flutter::DlPaint save_paint;
1070 SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
1071 Matrix translate_matrix =
1072 Matrix::MakeTranslation({translation[0], translation[1]});
1073 if (enable_save_layer) {
1074 auto filter = flutter::DlMatrixImageFilter(
1075 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1076 save_paint.setImageFilter(filter.shared());
1077 builder.SaveLayer(&bounds, &save_paint);
1078 } else {
1079 builder.Save();
1080 builder.Transform(translate_matrix);
1081 }
1082
1083 Matrix filter_matrix;
1084 filter_matrix.Translate({150, 150});
1085 filter_matrix.Scale({0.2f, 0.2f});
1086 filter_matrix.Translate({-150, -150});
1087 auto filter = flutter::DlMatrixImageFilter(
1088 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1089
1090 save_paint.setImageFilter(filter.shared());
1091
1092 builder.SaveLayer(&bounds, &save_paint);
1093 flutter::DlPaint paint2;
1094 paint2.setColor(flutter::DlColor::kBlue());
1095 builder.DrawRect(bounds, paint2);
1096 builder.Restore();
1097 builder.Restore();
1098 return builder.Build();
1099 };
1100
1101 ASSERT_TRUE(OpenPlaygroundHere(callback));
1102 }

References impeller::Matrix::MakeTranslation(), impeller::Matrix::Scale(), and impeller::Matrix::Translate().

## ◆ TEST_P() [327/494]

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() [328/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 837 of file dl_unittests.cc.

837 {
838 flutter::DisplayListBuilder builder;
839 std::vector<flutter::DlStrokeCap> caps = {
840 flutter::DlStrokeCap::kButt,
841 flutter::DlStrokeCap::kRound,
842 flutter::DlStrokeCap::kSquare,
843 };
844 flutter::DlPaint paint =
845 flutter::DlPaint() //
846 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
847 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
848 .setStrokeCap(flutter::DlStrokeCap::kButt) //
849 .setStrokeWidth(20);
850 SkPath path = SkPath().addPoly({{150, 50}, {150, 50}}, false);
851 for (auto cap : caps) {
852 paint.setStrokeCap(cap);
853 builder.DrawLine(SkPoint{50, 50}, SkPoint{50, 50}, paint);
854 builder.DrawPath(path, paint);
855 builder.Translate(0, 150);
856 }
857 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
858 }

## ◆ TEST_P() [329/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 909 of file dl_unittests.cc.

909 {
910 flutter::DisplayListBuilder builder;
911 std::vector<flutter::DlStrokeCap> caps = {
912 flutter::DlStrokeCap::kButt,
913 flutter::DlStrokeCap::kRound,
914 flutter::DlStrokeCap::kSquare,
915 };
916 flutter::DlPaint paint = //
917 flutter::DlPaint() //
918 .setColor(flutter::DlColor::kWhite()) //
919 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
920 .setStrokeWidth(0);
921 flutter::DlPaint outline_paint = //
922 flutter::DlPaint() //
923 .setColor(flutter::DlColor::kYellow()) //
924 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
925 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
926 .setStrokeWidth(1);
927 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
928 for (auto cap : caps) {
929 paint.setStrokeCap(cap);
930 builder.DrawLine(SkPoint{50, 50}, SkPoint{60, 50}, paint);
931 builder.DrawRect(SkRect{45, 45, 65, 55}, outline_paint);
932 builder.DrawLine(SkPoint{100, 50}, SkPoint{100, 50}, paint);
933 if (cap != flutter::DlStrokeCap::kButt) {
934 builder.DrawRect(SkRect{95, 45, 105, 55}, outline_paint);
935 }
936 builder.DrawPath(path, paint);
937 builder.DrawRect(path.getBounds().makeOutset(5, 5), outline_paint);
938 builder.Translate(0, 150);
939 }
940 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
941 }

## ◆ TEST_P() [330/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1336 of file dl_unittests.cc.

1336 {
1337 flutter::DisplayListBuilder builder;
1338
1339 flutter::DlPaint fill_paint = //
1340 flutter::DlPaint() //
1341 .setColor(flutter::DlColor::kBlue()) //
1342 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1343 .setStrokeWidth(10);
1344 flutter::DlPaint stroke_paint = //
1345 flutter::DlPaint() //
1346 .setColor(flutter::DlColor::kGreen()) //
1347 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1348 .setStrokeWidth(10);
1349
1350 builder.DrawRRect(
1351 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1352 fill_paint);
1353 builder.DrawRRect(
1354 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1355 stroke_paint);
1356
1357 builder.DrawRRect(
1358 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1359 fill_paint);
1360 builder.DrawRRect(
1361 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1362 stroke_paint);
1363
1364 flutter::DlPaint reference_paint = //
1365 flutter::DlPaint() //
1366 .setColor(flutter::DlColor::kMidGrey()) //
1367 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1368 .setStrokeWidth(10);
1369
1370 builder.DrawRRect(
1371 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1372 reference_paint);
1373 builder.DrawRRect(
1374 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1375 reference_paint);
1376
1377 flutter::DlPaint clip_fill_paint = //
1378 flutter::DlPaint() //
1379 .setColor(flutter::DlColor::kCyan()) //
1380 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1381 .setStrokeWidth(10);
1382
1383 builder.Save();
1384 builder.ClipRRect(
1385 SkRRect::MakeRectXY(SkRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1386 builder.DrawPaint(clip_fill_paint);
1387 builder.Restore();
1388
1389 builder.Save();
1390 builder.ClipRRect(
1391 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1392 builder.DrawPaint(clip_fill_paint);
1393 builder.Restore();
1394
1395 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1396 }

## ◆ TEST_P() [331/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawMaskBlursThatMightUseSaveLayers |
| ) |  |

Definition at line 1512 of file dl_unittests.cc.

1512 {
1513 flutter::DisplayListBuilder builder;
1514 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1515 Vector2 scale = GetContentScale();
1516 builder.Scale(scale.x, scale.y);
1517
1518 builder.Save();
1519 // We need a small transform op to avoid a deferred save
1520 builder.Translate(1.0f, 1.0f);
1521 auto solid_filter =
1522 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1523 flutter::DlPaint solid_alpha_paint =
1524 flutter::DlPaint() //
1525 .setMaskFilter(solid_filter) //
1526 .setColor(flutter::DlColor::kBlue()) //
1527 .setAlpha(0x7f);
1528 for (int x = 1; x <= 4; x++) {
1529 for (int y = 1; y <= 4; y++) {
1530 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1531 solid_alpha_paint);
1532 }
1533 }
1534 builder.Restore();
1535
1536 builder.Save();
1537 builder.Translate(500.0f, 0.0f);
1538 auto normal_filter =
1539 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1540 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1541 Matrix::MakeRotationZ(Degrees(10)), flutter::DlImageSampling::kLinear);
1542 flutter::DlPaint normal_if_paint =
1543 flutter::DlPaint() //
1544 .setMaskFilter(solid_filter) //
1545 .setImageFilter(rotate_if) //
1546 .setColor(flutter::DlColor::kGreen()) //
1547 .setAlpha(0x7f);
1548 for (int x = 1; x <= 4; x++) {
1549 for (int y = 1; y <= 4; y++) {
1550 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1551 normal_if_paint);
1552 }
1553 }
1554 builder.Restore();
1555
1556 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1557 }

References impeller::Matrix::MakeRotationZ(), scale, and x.

## ◆ TEST_P() [332/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1489 of file dl_unittests.cc.

1489 {
1490 flutter::DisplayListBuilder builder;
1491 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1492
1493 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1494 builder.DrawCircle(SkPoint{300, 300}, 200,
1495 flutter::DlPaint().setMaskFilter(&filter));
1496
1497 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1498 flutter::DlColor::kGreen()};
1499 const float stops[2] = {0.0, 1.0};
1500 auto linear = flutter::DlColorSource::MakeLinear(
1501 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1502 flutter::DlTileMode::kRepeat);
1503 flutter::DlPaint blend_paint =
1504 flutter::DlPaint() //
1505 .setColorSource(linear) //
1506 .setBlendMode(flutter::DlBlendMode::kScreen);
1507 builder.DrawPaint(blend_paint);
1508
1509 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1510 }

## ◆ TEST_P() [333/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1298 of file dl_unittests.cc.

1298 {
1299 flutter::DisplayListBuilder builder;
1300 std::vector<flutter::DlStrokeJoin> joins = {
1301 flutter::DlStrokeJoin::kBevel,
1302 flutter::DlStrokeJoin::kRound,
1303 flutter::DlStrokeJoin::kMiter,
1304 };
1305 flutter::DlPaint paint = //
1306 flutter::DlPaint() //
1307 .setColor(flutter::DlColor::kWhite()) //
1308 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1309 .setStrokeWidth(10);
1310 flutter::DlPaint stroke_paint = //
1311 flutter::DlPaint() //
1312 .setColor(flutter::DlColor::kWhite()) //
1313 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1314 .setStrokeWidth(10);
1315 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1316
1317 builder.Translate(300, 50);
1318 builder.Scale(0.8, 0.8);
1319 for (auto join : joins) {
1320 paint.setStrokeJoin(join);
1321 stroke_paint.setStrokeJoin(join);
1322 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1323 builder.DrawRect(SkRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1324 builder.DrawRRect(
1325 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 0, 100, 100), 30, 30), paint);
1326 builder.DrawRRect(
1327 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1328 stroke_paint);
1329 builder.DrawCircle(SkPoint{350, 50}, 50, paint);
1330 builder.DrawCircle(SkPoint{350, 200}, 50, stroke_paint);
1331 builder.Translate(0, 300);
1332 }
1333 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1334 }

## ◆ TEST_P() [334/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1398 of file dl_unittests.cc.

1398 {
1399 std::vector<const char*> blend_mode_names;
1400 std::vector<flutter::DlBlendMode> blend_mode_values;
1401 {
1402 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1403 // Pipeline blends (Porter-Duff alpha compositing)
1404 {"Clear", flutter::DlBlendMode::kClear},
1405 {"Source", flutter::DlBlendMode::kSrc},
1406 {"Destination", flutter::DlBlendMode::kDst},
1407 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1408 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1409 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1410 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1411 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1412 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1413 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1414 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1415 {"Xor", flutter::DlBlendMode::kXor},
1416 {"Plus", flutter::DlBlendMode::kPlus},
1417 {"Modulate", flutter::DlBlendMode::kModulate},
1418 // Advanced blends (color component blends)
1419 {"Screen", flutter::DlBlendMode::kScreen},
1420 {"Overlay", flutter::DlBlendMode::kOverlay},
1421 {"Darken", flutter::DlBlendMode::kDarken},
1422 {"Lighten", flutter::DlBlendMode::kLighten},
1423 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1424 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1425 {"HardLight", flutter::DlBlendMode::kHardLight},
1426 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1427 {"Difference", flutter::DlBlendMode::kDifference},
1428 {"Exclusion", flutter::DlBlendMode::kExclusion},
1429 {"Multiply", flutter::DlBlendMode::kMultiply},
1430 {"Hue", flutter::DlBlendMode::kHue},
1431 {"Saturation", flutter::DlBlendMode::kSaturation},
1432 {"Color", flutter::DlBlendMode::kColor},
1433 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1434 };
1435 assert(blends.size() ==
1436 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1437 for (const auto& [name, mode] : blends) {
1438 blend_mode_names.push_back(name);
1439 blend_mode_values.push_back(mode);
1440 }
1441 }
1442
1443 auto callback = [&]() {
1444 static int current_blend_index = 3;
1445 static float dst_alpha = 1;
1446 static float src_alpha = 1;
1447 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1448 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1449 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1450 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1451
1452 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1453 {
1454 ImGui::ListBox("Blending mode", &current_blend_index,
1455 blend_mode_names.data(), blend_mode_names.size());
1456 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1457 ImGui::ColorEdit4("Color A", color0);
1458 ImGui::ColorEdit4("Color B", color1);
1459 ImGui::ColorEdit4("Color C", color2);
1460 ImGui::ColorEdit4("Source Color", src_color);
1461 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1462 }
1463 ImGui::End();
1464
1465 std::vector<DlPoint> positions = {DlPoint(100, 300), //
1466 DlPoint(200, 100), //
1467 DlPoint(300, 300)};
1468 std::vector<flutter::DlColor> colors = {
1469 toColor(color0).modulateOpacity(dst_alpha),
1470 toColor(color1).modulateOpacity(dst_alpha),
1471 toColor(color2).modulateOpacity(dst_alpha)};
1472
1473 auto vertices = flutter::DlVertices::Make(
1474 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1475 /*texture_coordinates=*/nullptr, colors.data());
1476
1477 flutter::DisplayListBuilder builder;
1478 flutter::DlPaint paint;
1479
1480 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1481 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1482 paint);
1483 return builder.Build();
1484 };
1485
1486 ASSERT_TRUE(OpenPlaygroundHere(callback));
1487 }

References toColor().

## ◆ TEST_P() [335/494]

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() [336/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1250 of file dl_unittests.cc.

1250 {
1251 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1252 flutter::DlBlurStyle::kNormal, 10);
1253
1254 flutter::DisplayListBuilder builder;
1255
1256 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1257 flutter::DlColor::kGreen()};
1258 std::array<float, 2> stops = {0, 1};
1259 auto texture = CreateTextureForFixture("airplane.jpg");
1260 auto matrix = flutter::DlMatrix::MakeTranslation({-300, -110});
1261 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1262 flutter::DlColorSource::MakeImage(
1263 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1264 flutter::DlTileMode::kRepeat, flutter::DlImageSampling::kLinear,
1265 &matrix),
1266 flutter::DlColorSource::MakeLinear(
1267 flutter::DlPoint(0, 0), flutter::DlPoint(100, 50), 2, colors.data(),
1268 stops.data(), flutter::DlTileMode::kClamp),
1269 };
1270
1271 builder.Save();
1272 builder.Translate(0, 100);
1273 for (const auto& color_source : color_sources) {
1274 flutter::DlPaint paint;
1275 paint.setColorSource(color_source);
1276 paint.setMaskFilter(blur_filter);
1277
1278 builder.Save();
1279 builder.Translate(100, 0);
1280 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1281 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeWH(100, 50), 30, 30),
1282 paint);
1283
1284 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1285 paint.setStrokeWidth(10);
1286 builder.Translate(200, 0);
1287 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeWH(100, 50), 30, 30),
1288 paint);
1289
1290 builder.Restore();
1291 builder.Translate(0, 100);
1292 }
1293 builder.Restore();
1294
1295 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1296 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [337/494]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImagePrecision |
| ) |  |

Definition at line 789 of file dl_unittests.cc.

789 {
790 // Draw a nine patch image with colored corners and verify that the corner
791 // color does not leak outside the intended region.
792 auto texture = CreateTextureForFixture("nine_patch_corners.png");
793 flutter::DisplayListBuilder builder;
794 builder.DrawImageNine(DlImageImpeller::Make(texture),
795 SkIRect::MakeXYWH(10, 10, 1, 1),
796 SkRect::MakeXYWH(0, 0, 200, 100),
797 flutter::DlFilterMode::kNearest, nullptr);
798 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
799 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [338/494]

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() [339/494]

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() [340/494]

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() [341/494]

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() [342/494]

impeller::testing::TEST_P | ( | EntityPassTargetTest | ,
|  | SwapWithMSAAImplicitResolve |
| ) |  |

Definition at line 47 of file entity_pass_target_unittests.cc.

47 {
48 auto content_context = GetContentContext();
49 auto buffer = content_context->GetContext()->CreateCommandBuffer();
50 auto context = content_context->GetContext();
51 auto& allocator = *context->GetResourceAllocator();
52
53 // Emulate implicit MSAA resolve by making color resolve and msaa texture the
54 // same.
55 RenderTarget render_target;
56 {
57 PixelFormat pixel_format =
58 context->GetCapabilities()->GetDefaultColorFormat();
59
60 // Create MSAA color texture.
61
62 TextureDescriptor color0_tex_desc;
63 color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
64 color0_tex_desc.type = TextureType::kTexture2DMultisample;
65 color0_tex_desc.sample_count = SampleCount::kCount4;
66 color0_tex_desc.format = pixel_format;
67 color0_tex_desc.size = ISize{100, 100};
68 color0_tex_desc.usage = TextureUsage::kRenderTarget;
69
70 auto color0_msaa_tex = allocator.CreateTexture(color0_tex_desc);
71
72 // Color attachment.
73
74 ColorAttachment color0;
75 color0.load_action = LoadAction::kDontCare;
76 color0.store_action = StoreAction::kStoreAndMultisampleResolve;
77 color0.texture = color0_msaa_tex;
78 color0.resolve_texture = color0_msaa_tex;
79
80 render_target.SetColorAttachment(color0, 0u);
81 render_target.SetStencilAttachment(std::nullopt);
82 }
83
84 auto entity_pass_target = EntityPassTarget(render_target, false, true);
85
86 auto color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
87 auto msaa_tex = color0.texture;
88 auto resolve_tex = color0.resolve_texture;
89
90 ASSERT_EQ(msaa_tex, resolve_tex);
91
92 FML_DCHECK(content_context);
93 entity_pass_target.Flip(*content_context);
94
95 color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
96
97 ASSERT_NE(msaa_tex, color0.texture);
98 ASSERT_NE(resolve_tex, color0.resolve_texture);
99 ASSERT_EQ(color0.texture, color0.resolve_texture);
100 }

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() [343/494]

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().GetColorAttachment(0);
35 auto msaa_tex = color0.texture;
36 auto resolve_tex = color0.resolve_texture;
37
38 FML_DCHECK(content_context);
39 entity_pass_target.Flip(*content_context);
40
41 color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
42
43 ASSERT_EQ(msaa_tex, color0.texture);
44 ASSERT_NE(resolve_tex, color0.resolve_texture);
45 }

## ◆ TEST_P() [344/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 829 of file entity_unittests.cc.

829 {
830 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
831 static float scale = 20;
832
833 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
834 ImGui::SliderFloat("Scale", &scale, 1, 100);
835 ImGui::End();
836
837 Entity entity;
838 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
839 auto path = PathBuilder{}
840 .MoveTo({97.325, 34.818})
841 .CubicCurveTo({98.50862885295136, 34.81812293973836},
842 {99.46822048142015, 33.85863261475589},
843 {99.46822048142015, 32.67499810206613})
844 .CubicCurveTo({99.46822048142015, 31.491363589376355},
845 {98.50862885295136, 30.53187326439389},
846 {97.32499434685802, 30.531998226542708})
847 .CubicCurveTo({96.14153655073771, 30.532123170035373},
848 {95.18222070648729, 31.491540299350355},
849 {95.18222070648729, 32.67499810206613})
850 .CubicCurveTo({95.18222070648729, 33.85845590478189},
851 {96.14153655073771, 34.81787303409686},
852 {97.32499434685802, 34.81799797758954})
853 .Close()
854 .TakePath();
855 entity.SetTransform(
856 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
857
858 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
859
860 auto contents = std::make_shared<SolidColorContents>();
861 contents->SetColor(Color::Red());
862 contents->SetGeometry(geom.get());
863
864 entity.SetContents(contents);
865 return entity.Render(context, pass);
866 };
867 ASSERT_TRUE(OpenPlaygroundHere(callback));
868 }

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() [345/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 698 of file entity_unittests.cc.

698 {
699 std::vector<const char*> blend_mode_names;
700 std::vector<BlendMode> blend_mode_values;
701 {
702 // Force an exhausiveness check with a switch. When adding blend modes,
703 // update this switch with a new name/value to make it selectable in the
704 // test GUI.
705
706 const BlendMode b{};
707 static_assert(b == BlendMode::kClear); // Ensure the first item in
708 // the switch is the first
709 // item in the enum.
710 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
711 switch (b) {
712 case BlendMode::kClear:
713 blend_mode_names.push_back("Clear");
714 blend_mode_values.push_back(BlendMode::kClear);
715 case BlendMode::kSource:
716 blend_mode_names.push_back("Source");
717 blend_mode_values.push_back(BlendMode::kSource);
718 case BlendMode::kDestination:
719 blend_mode_names.push_back("Destination");
720 blend_mode_values.push_back(BlendMode::kDestination);
721 case BlendMode::kSourceOver:
722 blend_mode_names.push_back("SourceOver");
723 blend_mode_values.push_back(BlendMode::kSourceOver);
724 case BlendMode::kDestinationOver:
725 blend_mode_names.push_back("DestinationOver");
726 blend_mode_values.push_back(BlendMode::kDestinationOver);
727 case BlendMode::kSourceIn:
728 blend_mode_names.push_back("SourceIn");
729 blend_mode_values.push_back(BlendMode::kSourceIn);
730 case BlendMode::kDestinationIn:
731 blend_mode_names.push_back("DestinationIn");
732 blend_mode_values.push_back(BlendMode::kDestinationIn);
733 case BlendMode::kSourceOut:
734 blend_mode_names.push_back("SourceOut");
735 blend_mode_values.push_back(BlendMode::kSourceOut);
736 case BlendMode::kDestinationOut:
737 blend_mode_names.push_back("DestinationOut");
738 blend_mode_values.push_back(BlendMode::kDestinationOut);
739 case BlendMode::kSourceATop:
740 blend_mode_names.push_back("SourceATop");
741 blend_mode_values.push_back(BlendMode::kSourceATop);
742 case BlendMode::kDestinationATop:
743 blend_mode_names.push_back("DestinationATop");
744 blend_mode_values.push_back(BlendMode::kDestinationATop);
745 case BlendMode::kXor:
746 blend_mode_names.push_back("Xor");
747 blend_mode_values.push_back(BlendMode::kXor);
748 case BlendMode::kPlus:
749 blend_mode_names.push_back("Plus");
750 blend_mode_values.push_back(BlendMode::kPlus);
751 case BlendMode::kModulate:
752 blend_mode_names.push_back("Modulate");
753 blend_mode_values.push_back(BlendMode::kModulate);
754 };
755 }
756
757 auto callback = [&](ContentContext& context, RenderPass& pass) {
758 auto world_matrix = Matrix::MakeScale(GetContentScale());
759 auto draw_rect = [&context, &pass, &world_matrix](
760 Rect rect, Color color, BlendMode blend_mode) -> bool {
761 using VS = SolidFillPipeline::VertexShader;
762 using FS = SolidFillPipeline::FragmentShader;
763
764 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
765 {
766 auto r = rect.GetLTRB();
767 vtx_builder.AddVertices({
768 {Point(r[0], r[1])},
769 {Point(r[2], r[1])},
770 {Point(r[2], r[3])},
771 {Point(r[0], r[1])},
772 {Point(r[2], r[3])},
773 {Point(r[0], r[3])},
774 });
775 }
776
777 pass.SetCommandLabel("Blended Rectangle");
778 auto options = OptionsFromPass(pass);
779 options.blend_mode = blend_mode;
780 options.primitive_type = PrimitiveType::kTriangle;
781 pass.SetPipeline(context.GetSolidFillPipeline(options));
782 pass.SetVertexBuffer(
783 vtx_builder.CreateVertexBuffer(context.GetTransientsBuffer()));
784
785 VS::FrameInfo frame_info;
786 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
787 VS::BindFrameInfo(
788 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
789 FS::FragInfo frag_info;
790 frag_info.color = color.Premultiply();
791 FS::BindFragInfo(
792 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
793 return pass.Draw().ok();
794 };
795
796 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
797 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
798 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
799 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
800 static int current_blend_index = 3;
801 ImGui::ListBox("Blending mode", &current_blend_index,
802 blend_mode_names.data(), blend_mode_names.size());
803 ImGui::End();
804
805 BlendMode selected_mode = blend_mode_values[current_blend_index];
806
807 Point a, b, c, d;
808 PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
809 PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
810 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
811 PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
812 PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
813 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
814
815 bool result = true;
816 result = result &&
817 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
818 pass.GetRenderTargetSize().height),
819 Color(), BlendMode::kClear);
820 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
821 BlendMode::kSourceOver);
822 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
823 selected_mode);
824 return result;
825 };
826 ASSERT_TRUE(OpenPlaygroundHere(callback));
827 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::saturated::b, 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() [346/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1258 of file entity_unittests.cc.

1258 {
1259 auto fill = std::make_shared<SolidColorContents>();
1260 auto geom = Geometry::MakeFillPath(
1261 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1262 fill->SetGeometry(geom.get());
1263 fill->SetColor(Color::CornflowerBlue());
1264 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1265 FilterInput::Make(fill), Radius{3}, Radius{4});
1266
1267 {
1268 Entity e;
1269 e.SetTransform(Matrix());
1270 auto actual = border_mask_blur->GetCoverage(e);
1271 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1272 ASSERT_TRUE(actual.has_value());
1273 ASSERT_RECT_NEAR(actual.value(), expected);
1274 }
1275
1276 {
1277 Entity e;
1278 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1279 auto actual = border_mask_blur->GetCoverage(e);
1280 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1281 ASSERT_TRUE(actual.has_value());
1282 ASSERT_RECT_NEAR(actual.value(), expected);
1283 }
1284 }

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() [347/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2251 of file entity_unittests.cc.

2251 {
2252 PathBuilder builder = {};
2253 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2254 Path path = builder.TakePath();
2255
2256 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2257
2258 auto geom = Geometry::MakeFillPath(path);
2259
2260 Entity entity;
2261 RenderTarget target =
2262 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2263 *GetContext(), {1, 1}, 1u);
2264 testing::MockRenderPass render_pass(GetContext(), target);
2265 auto position_result =
2266 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2267
2268 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2269
2270 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2271 }

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

## ◆ TEST_P() [348/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 72 of file entity_unittests.cc.

72 {
73 Entity entity;
74 ASSERT_TRUE(entity.GetTransform().IsIdentity());
75 }

References impeller::Entity::GetTransform(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [349/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 366 of file entity_unittests.cc.

366 {
367 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
368 const char* input_axis[] = {"X", "Y", "Z"};
369 static int rotation_axis_index = 0;
370 static float rotation = 0;
371 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
372 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
373 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
374 sizeof(input_axis) / sizeof(char*));
375 Matrix rotation_matrix;
376 switch (rotation_axis_index) {
377 case 0:
378 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
379 break;
380 case 1:
381 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
382 break;
383 case 2:
384 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
385 break;
386 default:
387 rotation_matrix = Matrix{};
388 break;
389 }
390
391 if (ImGui::Button("Reset")) {
392 rotation = 0;
393 }
394 ImGui::End();
395 Matrix current_transform =
396 Matrix::MakeScale(GetContentScale())
397 .MakeTranslation(
398 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
399 pass.GetRenderTargetSize().height / 2.0)));
400 Matrix result_transform = current_transform * rotation_matrix;
401 Path path =
402 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
403
404 Entity entity;
405 entity.SetTransform(result_transform);
406
407 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
408
409 auto contents = std::make_shared<SolidColorContents>();
410 contents->SetColor(Color::Red());
411 contents->SetGeometry(geom.get());
412
413 entity.SetContents(contents);
414 return entity.Render(context, pass);
415 };
416 ASSERT_TRUE(OpenPlaygroundHere(callback));
417 }

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() [350/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2273 of file entity_unittests.cc.

2273 {
2274 PathBuilder builder = {};
2275 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2276 Path path = builder.TakePath();
2277
2278 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2279
2280 auto contents = std::make_shared<SolidColorContents>();
2281 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
2282 contents->SetGeometry(geom.get());
2283 contents->SetColor(Color::Red());
2284
2285 Entity entity;
2286 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2287 entity.SetContents(contents);
2288
2289 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2290 }

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() [351/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2092 of file entity_unittests.cc.

2092 {
2093 Entity entity;
2094 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2095 auto src_contents = std::make_shared<SolidColorContents>();
2096 auto src_geom = Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000));
2097 src_contents->SetGeometry(src_geom.get());
2098 src_contents->SetColor(Color::Red());
2099
2100 auto dst_contents = std::make_shared<SolidColorContents>();
2101 auto dst_geom = Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000));
2102 dst_contents->SetGeometry(dst_geom.get());
2103 dst_contents->SetColor(Color::Blue());
2104
2105 auto contents = ColorFilterContents::MakeBlend(
2106 BlendMode::kSourceOver, {FilterInput::Make(dst_contents, false),
2107 FilterInput::Make(src_contents, false)});
2108 entity.SetContents(std::move(contents));
2109 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2110 }

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() [352/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 1859 of file entity_unittests.cc.

1859 {
1860 auto image = CreateTextureForFixture("boston.jpg");
1861 auto filter = ColorFilterContents::MakeBlend(
1862 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
1863
1864 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1865 Entity entity;
1866 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1867 Matrix::MakeTranslation({500, 300}) *
1868 Matrix::MakeScale(Vector2{0.5, 0.5}));
1869 entity.SetContents(filter);
1870 return entity.Render(context, pass);
1871 };
1872 ASSERT_TRUE(OpenPlaygroundHere(callback));
1873 }

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() [353/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 1875 of file entity_unittests.cc.

1875 {
1876 auto image = CreateTextureForFixture("boston.jpg");
1877 auto filter = ColorFilterContents::MakeBlend(
1878 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
1879
1880 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1881 Entity entity;
1882 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1883 Matrix::MakeTranslation({500, 300}) *
1884 Matrix::MakeScale(Vector2{0.5, 0.5}));
1885 entity.SetContents(filter);
1886 return entity.Render(context, pass);
1887 };
1888 ASSERT_TRUE(OpenPlaygroundHere(callback));
1889 }

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() [354/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 1907 of file entity_unittests.cc.

1907 {
1908 auto image = CreateTextureForFixture("boston.jpg");
1909 auto filter = ColorFilterContents::MakeBlend(
1910 BlendMode::kDestination, FilterInput::Make({image}), Color::Red());
1911
1912 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1913 Entity entity;
1914 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1915 Matrix::MakeTranslation({500, 300}) *
1916 Matrix::MakeScale(Vector2{0.5, 0.5}));
1917 entity.SetContents(filter);
1918 return entity.Render(context, pass);
1919 };
1920 ASSERT_TRUE(OpenPlaygroundHere(callback));
1921 }

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() [355/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 1891 of file entity_unittests.cc.

1891 {
1892 auto image = CreateTextureForFixture("boston.jpg");
1893 auto filter = ColorFilterContents::MakeBlend(
1894 BlendMode::kSource, FilterInput::Make({image}), Color::Red());
1895
1896 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1897 Entity entity;
1898 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1899 Matrix::MakeTranslation({500, 300}) *
1900 Matrix::MakeScale(Vector2{0.5, 0.5}));
1901 entity.SetContents(filter);
1902 return entity.Render(context, pass);
1903 };
1904 ASSERT_TRUE(OpenPlaygroundHere(callback));
1905 }

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() [356/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 1923 of file entity_unittests.cc.

1923 {
1924 auto image = CreateTextureForFixture("boston.jpg");
1925 auto filter = ColorFilterContents::MakeBlend(
1926 BlendMode::kSourceIn, FilterInput::Make({image}), Color::Red());
1927
1928 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1929 Entity entity;
1930 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1931 Matrix::MakeTranslation({500, 300}) *
1932 Matrix::MakeScale(Vector2{0.5, 0.5}));
1933 entity.SetContents(filter);
1934 return entity.Render(context, pass);
1935 };
1936 ASSERT_TRUE(OpenPlaygroundHere(callback));
1937 }

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() [357/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1385 of file entity_unittests.cc.

1385 {
1386 // Set up a simple color background.
1387 auto fill = std::make_shared<SolidColorContents>();
1388 auto geom = Geometry::MakeFillPath(
1389 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1390 fill->SetGeometry(geom.get());
1391 fill->SetColor(Color::Coral());
1392
1393 // Set the color matrix filter.
1394 ColorMatrix matrix = {
1395 1, 1, 1, 1, 1, //
1396 1, 1, 1, 1, 1, //
1397 1, 1, 1, 1, 1, //
1398 1, 1, 1, 1, 1, //
1399 };
1400
1401 auto filter =
1402 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1403
1404 Entity e;
1405 e.SetTransform(Matrix());
1406
1407 // Confirm that the actual filter coverage matches the expected coverage.
1408 auto actual = filter->GetCoverage(e);
1409 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1410
1411 ASSERT_TRUE(actual.has_value());
1412 ASSERT_RECT_NEAR(actual.value(), expected);
1413 }

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() [358/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1415 of file entity_unittests.cc.

1415 {
1416 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1417 ASSERT_TRUE(bay_bridge);
1418
1419 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1420 // UI state.
1421 static ColorMatrix color_matrix = {
1422 1, 0, 0, 0, 0, //
1423 0, 3, 0, 0, 0, //
1424 0, 0, 1, 0, 0, //
1425 0, 0, 0, 1, 0, //
1426 };
1427 static float offset[2] = {500, 400};
1428 static float rotation = 0;
1429 static float scale[2] = {0.65, 0.65};
1430 static float skew[2] = {0, 0};
1431
1432 // Define the ImGui
1433 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1434 {
1435 std::string label = "##1";
1436 for (int i = 0; i < 20; i += 5) {
1437 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1438 &(color_matrix.array[i]), 5, nullptr, nullptr,
1439 "%.2f", 0);
1440 label[2]++;
1441 }
1442
1443 ImGui::SliderFloat2("Translation", &offset[0], 0,
1444 pass.GetRenderTargetSize().width);
1445 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1446 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1447 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1448 }
1449 ImGui::End();
1450
1451 // Set the color matrix filter.
1452 auto filter = ColorFilterContents::MakeColorMatrix(
1453 FilterInput::Make(bay_bridge), color_matrix);
1454
1455 // Define the entity with the color matrix filter.
1456 Entity entity;
1457 entity.SetTransform(
1458 Matrix::MakeScale(GetContentScale()) *
1459 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1460 Matrix::MakeRotationZ(Radians(rotation)) *
1461 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1462 Matrix::MakeSkew(skew[0], skew[1]) *
1463 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1464 entity.SetContents(filter);
1465 entity.Render(context, pass);
1466
1467 return true;
1468 };
1469
1470 ASSERT_TRUE(OpenPlaygroundHere(callback));
1471 }

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() [359/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 1980 of file entity_unittests.cc.

1980 {
1981 Matrix matrix;
1982 ConicalGradientContents contents;
1983 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
1984 contents.SetGeometry(geom.get());
1985
1986 contents.SetColors({Color::CornflowerBlue()});
1987 EXPECT_FALSE(contents.IsOpaque(matrix));
1988 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
1989 EXPECT_FALSE(contents.IsOpaque(matrix));
1990
1991 // Create stroked path that required alpha coverage.
1992 geom = Geometry::MakeStrokePath(
1993 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
1994 /*stroke_width=*/0.05);
1995 contents.SetGeometry(geom.get());
1996 contents.SetColors({Color::CornflowerBlue()});
1997
1998 EXPECT_FALSE(contents.IsOpaque(matrix));
1999 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2159 of file entity_unittests.cc.

2159 {
2160 ContentContextOptions opts;
2161 auto hash_a = opts.ToKey();
2162
2163 opts.blend_mode = BlendMode::kColorBurn;
2164 auto hash_b = opts.ToKey();
2165
2166 opts.has_depth_stencil_attachments = false;
2167 auto hash_c = opts.ToKey();
2168
2169 opts.primitive_type = PrimitiveType::kPoint;
2170 auto hash_d = opts.ToKey();
2171
2172 EXPECT_NE(hash_a, hash_b);
2173 EXPECT_NE(hash_b, hash_c);
2174 EXPECT_NE(hash_c, hash_d);
2175 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::kColorBurn, impeller::kPoint, impeller::ContentContextOptions::primitive_type, and impeller::ContentContextOptions::ToKey().

## ◆ TEST_P() [361/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1196 of file entity_unittests.cc.

1196 {
1197 Entity entity;
1198 entity.SetContents(std::make_shared<SolidColorContents>());
1199 ASSERT_FALSE(entity.GetCoverage().has_value());
1200 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [362/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 1939 of file entity_unittests.cc.

1939 {
1940 auto arrow_head = PathBuilder{}
1941 .MoveTo({50, 120})
1942 .LineTo({120, 190})
1943 .LineTo({190, 120})
1944 .TakePath();
1945 auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound,
1946 Join::kRound);
1947
1948 auto transform = Matrix::MakeTranslation({300, 300}) *
1949 Matrix::MakeRotationZ(Radians(kPiOver2));
1950 // Note that e[0][0] used to be tested here, but it was -epsilon solely
1951 // due to floating point inaccuracy in the transcendental trig functions.
1952 // e[1][0] is the intended negative value that we care about (-1.0) as it
1953 // comes from the rotation of pi/2.
1954 EXPECT_LT(transform.e[1][0], 0.0f);
1955 auto coverage = geometry->GetCoverage(transform);
1956 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
1957 }

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() [363/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 419 of file entity_unittests.cc.

419 {
420 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
421 Path path =
422 PathBuilder{}
423 .MoveTo({359.934, 96.6335})
424 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
425 {354.673, 96.8895})
426 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
427 {354.367, 96.9075})
428 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
429 {349.259, 97.2355})
430 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
431 {348.625, 97.2834})
432 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
433 {343.789, 97.6722})
434 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
435 {342.703, 97.7734})
436 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
437 {338.246, 98.207})
438 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
439 {336.612, 98.3894})
440 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
441 {332.623, 98.8476})
442 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
443 {332.237, 98.8982})
444 .LineTo({332.237, 102.601})
445 .LineTo({321.778, 102.601})
446 .LineTo({321.778, 100.382})
447 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
448 {321.161, 100.476})
449 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
450 {315.332, 101.479})
451 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
452 {315.301, 101.484})
453 .LineTo({310.017, 105.94})
454 .LineTo({309.779, 105.427})
455 .LineTo({314.403, 101.651})
456 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
457 {314.368, 101.658})
458 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
459 {308.846, 102.748})
460 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
461 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
462 {303.425, 103.936})
463 .LineTo({299.105, 107.578})
464 .LineTo({298.867, 107.065})
465 .LineTo({302.394, 104.185})
466 .LineTo({302.412, 104.171})
467 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
468 {299.344, 104.921})
469 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
470 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
471 {291.462, 106.979})
472 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
473 {290.471, 107.257})
474 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
475 {287.449, 108.139})
476 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
477 {284.536, 109.035})
478 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
479 {281.952, 109.859})
480 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
481 {279.633, 110.638})
482 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
483 {276.803, 111.607})
484 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
485 {276.672, 111.653})
486 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
487 {271.721, 113.463})
488 .LineTo({271.717, 113.449})
489 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
490 {270.963, 113.628})
491 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
492 {270.748, 113.682})
493 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
494 {269.839, 113.926})
495 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
496 {269.681, 113.972})
497 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
498 {268.756, 114.239})
499 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
500 {268.367, 114.354})
501 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
502 {267.752, 114.54})
503 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
504 {253.564, 119.252})
505 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
506 {253.538, 119.261})
507 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
508 {248.189, 121.131})
509 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
510 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
511 {245.975, 121.912})
512 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
513 {244.698, 122.364})
514 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
515 {242.794, 123.04})
516 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
517 {240.961, 123.693})
518 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
519 {240.052, 124.018})
520 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
521 .LineTo({237.164, 125.003})
522 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
523 {235.81, 125.538})
524 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
525 {234.592, 125.977})
526 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
527 {234.59, 125.977})
528 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
529 {192.381, 141.429})
530 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
531 .LineTo({360, 160})
532 .LineTo({360, 119.256})
533 .LineTo({360, 106.332})
534 .LineTo({360, 96.6307})
535 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
536 {359.934, 96.6335})
537 .Close()
538 .MoveTo({337.336, 124.143})
539 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
540 {338.903, 121.511})
541 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
542 {337.336, 124.143})
543 .Close()
544 .MoveTo({340.082, 121.849})
545 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
546 {340.046, 122.075})
547 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
548 {340.023, 122.177})
549 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
550 {339.952, 122.437})
551 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
552 {339.918, 122.544})
553 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
554 {339.75, 122.938})
555 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
556 {339.74, 122.955})
557 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
558 {339.501, 123.328})
559 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
560 {339.41, 123.438})
561 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
562 {339.145, 123.714})
563 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
564 {339.025, 123.821})
565 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
566 {338.539, 124.143})
567 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
568 {338.58, 123.626})
569 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
570 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
571 {338.704, 123.151})
572 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
573 {338.714, 123.117})
574 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
575 {338.905, 122.712})
576 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
577 {338.922, 122.682})
578 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
579 {339.155, 122.34})
580 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
581 {339.172, 122.319})
582 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
583 {339.425, 122.037})
584 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
585 {339.435, 122.027})
586 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
587 {340.106, 121.511})
588 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
589 {340.082, 121.849})
590 .Close()
591 .MoveTo({340.678, 113.245})
592 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
593 {340.135, 113.775})
594 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
595 {339.115, 114.151})
596 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
597 {336.448, 114.516})
598 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
599 {334.384, 114.513})
600 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
601 {333.605, 114.424})
602 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
603 {331.41, 113.883})
604 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
605 {330.672, 112.813})
606 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
607 {334.526, 113.833})
608 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
609 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
610 {332.76, 110.402})
611 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
612 {335.228, 113.395})
613 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
614 {335.661, 109.592})
615 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
616 {336.07, 113.389})
617 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
618 {338.563, 110.402})
619 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
620 {336.753, 113.784})
621 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
622 {336.796, 113.833})
623 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
624 {340.65, 112.813})
625 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
626 {340.678, 113.245})
627 .Close()
628 .MoveTo({346.357, 106.771})
629 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
630 {347.924, 104.139})
631 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
632 {346.357, 106.771})
633 .Close()
634 .MoveTo({347.56, 106.771})
635 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
636 {349.127, 104.139})
637 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
638 {347.56, 106.771})
639 .Close()
640 .TakePath();
641 Entity entity;
642 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
643
644 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
645
646 auto contents = std::make_shared<SolidColorContents>();
647 contents->SetColor(Color::Red());
648 contents->SetGeometry(geom.get());
649
650 entity.SetContents(contents);
651 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
652 }

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() [364/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 337 of file entity_unittests.cc.

337 {
338 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
339 Path path =
340 PathBuilder{}
341 .MoveTo({237.164, 125.003})
342 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
343 {235.81, 125.538})
344 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
345 {234.592, 125.977})
346 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
347 {234.59, 125.977})
348 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
349 {192.381, 141.429})
350 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
351 .Close()
352 .TakePath();
353 Entity entity;
354 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
355
356 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
357
358 auto contents = std::make_shared<SolidColorContents>();
359 contents->SetColor(Color::Red());
360 contents->SetGeometry(geom.get());
361
362 entity.SetContents(contents);
363 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
364 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [365/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2143 of file entity_unittests.cc.

2143 {
2144 auto content_context = GetContentContext();
2145 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2146 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2147 });
2148
2149 auto decal_supported = static_cast<Scalar>(
2150 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2151 std::vector<Scalar> expected_constants = {decal_supported};
2152 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2153 expected_constants);
2154 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [366/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawRoundSuperEllipse |
| ) |  |

Definition at line 2325 of file entity_unittests.cc.

2325 {
2326 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2327 // UI state.
2328 static float center[2] = {830, 830};
2329 static float size[2] = {600, 600};
2330 static bool horizontal_symmetry = true;
2331 static bool vertical_symmetry = true;
2332 static bool corner_symmetry = true;
2333
2334 // Initially radius_tl[0] will be mirrored to all 8 values since all 3
2335 // symmetries are enabled.
2336 static std::array<float, 2> radius_tl = {200};
2337 static std::array<float, 2> radius_tr;
2338 static std::array<float, 2> radius_bl;
2339 static std::array<float, 2> radius_br;
2340
2341 auto AddRadiusControl = [](std::array<float, 2>& radii, const char* tb_name,
2342 const char* lr_name) {
2343 std::string name = "Radius";
2344 if (!horizontal_symmetry || !vertical_symmetry) {
2345 name += ":";
2346 }
2347 if (!vertical_symmetry) {
2348 name = name + " " + tb_name;
2349 }
2350 if (!horizontal_symmetry) {
2351 name = name + " " + lr_name;
2352 }
2353 if (corner_symmetry) {
2354 ImGui::SliderFloat(name.c_str(), radii.data(), 0, 1000);
2355 } else {
2356 ImGui::SliderFloat2(name.c_str(), radii.data(), 0, 1000);
2357 }
2358 };
2359
2360 if (corner_symmetry) {
2361 radius_tl[1] = radius_tl[0];
2362 radius_tr[1] = radius_tr[0];
2363 radius_bl[1] = radius_bl[0];
2364 radius_br[1] = radius_br[0];
2365 }
2366
2367 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2368 {
2369 ImGui::SliderFloat2("Center", center, 0, 1000);
2370 ImGui::SliderFloat2("Size", size, 0, 1000);
2371 ImGui::Checkbox("Symmetry: Horizontal", &horizontal_symmetry);
2372 ImGui::Checkbox("Symmetry: Vertical", &vertical_symmetry);
2373 ImGui::Checkbox("Symmetry: Corners", &corner_symmetry);
2374 AddRadiusControl(radius_tl, "Top", "Left");
2375 if (!horizontal_symmetry) {
2376 AddRadiusControl(radius_tr, "Top", "Right");
2377 } else {
2378 radius_tr = radius_tl;
2379 }
2380 if (!vertical_symmetry) {
2381 AddRadiusControl(radius_bl, "Bottom", "Left");
2382 } else {
2383 radius_bl = radius_tl;
2384 }
2385 if (!horizontal_symmetry && !vertical_symmetry) {
2386 AddRadiusControl(radius_br, "Bottom", "Right");
2387 } else {
2388 if (horizontal_symmetry) {
2389 radius_br = radius_bl;
2390 } else {
2391 radius_br = radius_tr;
2392 }
2393 }
2394 }
2395
2396 ImGui::End();
2397
2398 RoundingRadii radii{
2399 .top_left = {radius_tl[0], radius_tl[1]},
2400 .top_right = {radius_tr[0], radius_tr[1]},
2401 .bottom_left = {radius_bl[0], radius_bl[1]},
2402 .bottom_right = {radius_br[0], radius_br[1]},
2403 };
2404
2405 auto contents = std::make_shared<SolidColorContents>();
2406 std::unique_ptr<RoundSuperellipseGeometry> geom =
2407 std::make_unique<RoundSuperellipseGeometry>(
2408 Rect::MakeOriginSize({center[0], center[1]}, {size[0], size[1]}),
2409 radii);
2410 contents->SetColor(Color::Red());
2411 contents->SetGeometry(geom.get());
2412
2413 Entity entity;
2414 entity.SetContents(contents);
2415
2416 return entity.Render(context, pass);
2417 };
2418
2419 ASSERT_TRUE(OpenPlaygroundHere(callback));
2420 }

References impeller::TRect< Scalar >::MakeOriginSize(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::RoundingRadii::top_left.

## ◆ TEST_P() [367/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawSuperEllipse |
| ) |  |

Definition at line 2292 of file entity_unittests.cc.

2292 {
2293 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2294 // UI state.
2295 static float alpha = 10;
2296 static float beta = 10;
2297 static float radius = 40;
2298 static int degree = 4;
2299 static Color color = Color::Red();
2300
2301 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2302 ImGui::SliderFloat("Alpha", &alpha, 0, 100);
2303 ImGui::SliderFloat("Beta", &beta, 0, 100);
2304 ImGui::SliderInt("Degreee", &degree, 1, 20);
2305 ImGui::SliderFloat("Radius", &radius, 0, 400);
2306 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
2307 ImGui::End();
2308
2309 auto contents = std::make_shared<SolidColorContents>();
2310 std::unique_ptr<SuperellipseGeometry> geom =
2311 std::make_unique<SuperellipseGeometry>(Point{400, 400}, radius, degree,
2312 alpha, beta);
2313 contents->SetColor(color);
2314 contents->SetGeometry(geom.get());
2315
2316 Entity entity;
2317 entity.SetContents(contents);
2318
2319 return entity.Render(context, pass);
2320 };
2321
2322 ASSERT_TRUE(OpenPlaygroundHere(callback));
2323 }

References impeller::Color::Red(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [368/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2237 of file entity_unittests.cc.

2237 {
2238 if (GetParam() != PlaygroundBackend::kVulkan) {
2239 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2240 }
2241 EXPECT_DEATH(
2242 // The easiest way to trigger a validation error is to try to compile
2243 // a shader with an unsupported pixel format.
2244 GetContentContext()->GetBlendColorBurnPipeline({
2245 .color_attachment_pixel_format = PixelFormat::kUnknown,
2246 .has_depth_stencil_attachments = false,
2247 }),
2248 "");
2249 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [369/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2203 of file entity_unittests.cc.

2203 {
2204 RenderTarget target;
2205 testing::MockRenderPass mock_pass(GetContext(), target);
2206
2207 auto get_result = [this, &mock_pass](const Path& path) {
2208 auto geometry = Geometry::MakeFillPath(
2209 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2210 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2211 };
2212
2213 // Convex path
2214 {
2215 GeometryResult result =
2216 get_result(PathBuilder{}
2217 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
2218 .SetConvexity(Convexity::kConvex)
2219 .TakePath());
2220 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2221 }
2222
2223 // Concave path
2224 {
2225 Path path = PathBuilder{}
2226 .MoveTo({0, 0})
2227 .LineTo({100, 0})
2228 .LineTo({100, 100})
2229 .LineTo({50, 50})
2230 .Close()
2231 .TakePath();
2232 GeometryResult result = get_result(path);
2233 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2234 }
2235 }

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() [370/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 77 of file entity_unittests.cc.

77 {
78 auto image = CreateTextureForFixture("boston.jpg");
79 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
80 FilterInput::Make({image}));
81
82 // Without the crop rect (default behavior).
83 {
84 auto actual = filter->GetCoverage({});
85 auto expected = Rect::MakeSize(image->GetSize());
86
87 ASSERT_TRUE(actual.has_value());
88 ASSERT_RECT_NEAR(actual.value(), expected);
89 }
90
91 // With the crop rect.
92 {
93 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
94 filter->SetCoverageHint(expected);
95 auto actual = filter->GetCoverage({});
96
97 ASSERT_TRUE(actual.has_value());
98 ASSERT_RECT_NEAR(actual.value(), expected);
99 }
100 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [371/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 870 of file entity_unittests.cc.

870 {
871 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
872 auto boston = CreateTextureForFixture("boston.jpg");
873 auto kalimba = CreateTextureForFixture("kalimba.jpg");
874 ASSERT_TRUE(bridge && boston && kalimba);
875
876 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
877 auto fi_bridge = FilterInput::Make(bridge);
878 auto fi_boston = FilterInput::Make(boston);
879 auto fi_kalimba = FilterInput::Make(kalimba);
880
881 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
882 BlendMode::kModulate, {fi_kalimba, fi_boston});
883
884 auto blend1 = ColorFilterContents::MakeBlend(
885 BlendMode::kScreen,
886 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
887
888 Entity entity;
889 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
890 Matrix::MakeTranslation({500, 300}) *
891 Matrix::MakeScale(Vector2{0.5, 0.5}));
892 entity.SetContents(blend1);
893 return entity.Render(context, pass);
894 };
895 ASSERT_TRUE(OpenPlaygroundHere(callback));
896 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [372/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 898 of file entity_unittests.cc.

898 {
899 auto boston =
900 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
901 ASSERT_TRUE(boston);
902
903 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
904 const char* input_type_names[] = {"Texture", "Solid Color"};
905 const char* blur_type_names[] = {"Image blur", "Mask blur"};
906 const char* pass_variation_names[] = {"New"};
907 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
908 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
909 const FilterContents::BlurStyle blur_styles[] = {
910 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
911 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
912 const Entity::TileMode tile_modes[] = {
913 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
914 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
915
916 // UI state.
917 static int selected_input_type = 0;
918 static Color input_color = Color::Black();
919 static int selected_blur_type = 0;
920 static int selected_pass_variation = 0;
921 static bool combined_sigma = false;
922 static float blur_amount_coarse[2] = {0, 0};
923 static float blur_amount_fine[2] = {10, 10};
924 static int selected_blur_style = 0;
925 static int selected_tile_mode = 3;
926 static Color cover_color(1, 0, 0, 0.2);
927 static Color bounds_color(0, 1, 0, 0.1);
928 static float offset[2] = {500, 400};
929 static float rotation = 0;
930 static float scale[2] = {0.65, 0.65};
931 static float skew[2] = {0, 0};
932 static float path_rect[4] = {0, 0,
933 static_cast<float>(boston->GetSize().width),
934 static_cast<float>(boston->GetSize().height)};
935
936 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
937 {
938 ImGui::Combo("Input type", &selected_input_type, input_type_names,
939 sizeof(input_type_names) / sizeof(char*));
940 if (selected_input_type == 0) {
941 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
942 } else {
943 ImGui::ColorEdit4("Input color",
944 reinterpret_cast<float*>(&input_color));
945 }
946 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
947 sizeof(blur_type_names) / sizeof(char*));
948 if (selected_blur_type == 0) {
949 ImGui::Combo("Pass variation", &selected_pass_variation,
950 pass_variation_names,
951 sizeof(pass_variation_names) / sizeof(char*));
952 }
953 ImGui::Checkbox("Combined sigma", &combined_sigma);
954 if (combined_sigma) {
955 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
956 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
957 blur_amount_coarse[1] = blur_amount_coarse[0];
958 blur_amount_fine[1] = blur_amount_fine[0];
959 } else {
960 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
961 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
962 }
963 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
964 sizeof(blur_style_names) / sizeof(char*));
965 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
966 sizeof(tile_mode_names) / sizeof(char*));
967 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
968 ImGui::ColorEdit4("Bounds color ",
969 reinterpret_cast<float*>(&bounds_color));
970 ImGui::SliderFloat2("Translation", offset, 0,
971 pass.GetRenderTargetSize().width);
972 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
973 ImGui::SliderFloat2("Scale", scale, 0, 3);
974 ImGui::SliderFloat2("Skew", skew, -3, 3);
975 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
976 }
977 ImGui::End();
978
979 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
980 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
981
982 std::shared_ptr<Contents> input;
983 Size input_size;
984
985 auto input_rect =
986 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
987
988 std::unique_ptr<Geometry> solid_color_input;
989 if (selected_input_type == 0) {
990 auto texture = std::make_shared<TextureContents>();
991 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
992 texture->SetDestinationRect(input_rect);
993 texture->SetTexture(boston);
994 texture->SetOpacity(input_color.alpha);
995
996 input = texture;
997 input_size = input_rect.GetSize();
998 } else {
999 auto fill = std::make_shared<SolidColorContents>();
1000 fill->SetColor(input_color);
1001 solid_color_input =
1002 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1003
1004 fill->SetGeometry(solid_color_input.get());
1005
1006 input = fill;
1007 input_size = input_rect.GetSize();
1008 }
1009
1010 std::shared_ptr<FilterContents> blur;
1011 switch (selected_pass_variation) {
1012 case 0:
1013 blur = std::make_shared<GaussianBlurFilterContents>(
1014 blur_sigma_x.sigma, blur_sigma_y.sigma,
1015 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1016 /*geometry=*/nullptr);
1017 blur->SetInputs({FilterInput::Make(input)});
1018 break;
1019 case 1:
1020 blur = FilterContents::MakeGaussianBlur(
1021 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1022 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1023 break;
1024 };
1025 FML_CHECK(blur);
1026
1027 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1028 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1029 blur_styles[selected_blur_style]);
1030
1031 auto ctm = Matrix::MakeScale(GetContentScale()) *
1032 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1033 Matrix::MakeRotationZ(Radians(rotation)) *
1034 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1035 Matrix::MakeSkew(skew[0], skew[1]) *
1036 Matrix::MakeTranslation(-Point(input_size) / 2);
1037
1038 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1039
1040 Entity entity;
1041 entity.SetContents(target_contents);
1042 entity.SetTransform(ctm);
1043
1044 entity.Render(context, pass);
1045
1046 // Renders a red "cover" rectangle that shows the original position of the
1047 // unfiltered input.
1048 Entity cover_entity;
1049 std::unique_ptr<Geometry> geom =
1050 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1051 auto contents = std::make_shared<SolidColorContents>();
1052 contents->SetColor(cover_color);
1053 contents->SetGeometry(geom.get());
1054 cover_entity.SetContents(std::move(contents));
1055 cover_entity.SetTransform(ctm);
1056 cover_entity.Render(context, pass);
1057
1058 // Renders a green bounding rect of the target filter.
1059 Entity bounds_entity;
1060 std::optional<Rect> target_contents_coverage =
1061 target_contents->GetCoverage(entity);
1062 if (target_contents_coverage.has_value()) {
1063 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
1064 PathBuilder{}
1065 .AddRect(target_contents->GetCoverage(entity).value())
1066 .TakePath());
1067 auto contents = std::make_shared<SolidColorContents>();
1068 contents->SetColor(bounds_color);
1069 contents->SetGeometry(geom.get());
1070
1071 bounds_entity.SetContents(contents);
1072 bounds_entity.SetTransform(Matrix());
1073 bounds_entity.Render(context, pass);
1074 }
1075
1076 return true;
1077 };
1078 ASSERT_TRUE(OpenPlaygroundHere(callback));
1079 }

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() [373/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 102 of file entity_unittests.cc.

102 {
103 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
104 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
105
106 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
107 Rect::MakeXYWH(200, 200, 200, 200));
108 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST_P() [374/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GiantLineStripPathAllocation |
| ) |  |

Definition at line 2512 of file entity_unittests.cc.

2512 {
2513 PathBuilder builder{};
2514 for (int i = 0; i < 10000; i++) {
2515 builder.LineTo(Point(i, i));
2516 }
2517 Path path = builder.TakePath();
2518
2519 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2520 Entity entity;
2521
2522 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
2523 GetContext()->GetIdleWaiter());
2524 auto tessellator = Tessellator();
2525
2526 auto vertex_buffer = tessellator.GenerateLineStrip(path, *host_buffer, 1.0);
2527
2528 // Validate the buffer data overflowed the small buffer
2529 EXPECT_GT(vertex_buffer.vertex_count, kPointArenaSize);
2530
2531 // Validate that there are no uninitialized points near the gap.
2532 Point* written_data = reinterpret_cast<Point*>(
2533 (vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2534 vertex_buffer.vertex_buffer.GetRange().offset));
2535
2536 std::vector<Point> expected = {
2537 Point(4093, 4093), //
2538 Point(4094, 4094), //
2539 Point(4095, 4095), //
2540 Point(4096, 4096), //
2541 Point(4097, 4097) //
2542 };
2543
2544 Point point = written_data[kPointArenaSize - 2];
2545 EXPECT_NEAR(point.x, expected[0].x, 0.1);
2546 EXPECT_NEAR(point.y, expected[0].y, 0.1);
2547
2548 point = written_data[kPointArenaSize - 1];
2549 EXPECT_NEAR(point.x, expected[1].x, 0.1);
2550 EXPECT_NEAR(point.y, expected[1].y, 0.1);
2551
2552 point = written_data[kPointArenaSize];
2553 EXPECT_NEAR(point.x, expected[2].x, 0.1);
2554 EXPECT_NEAR(point.y, expected[2].y, 0.1);
2555
2556 point = written_data[kPointArenaSize + 1];
2557 EXPECT_NEAR(point.x, expected[3].x, 0.1);
2558 EXPECT_NEAR(point.y, expected[3].y, 0.1);
2559
2560 point = written_data[kPointArenaSize + 2];
2561 EXPECT_NEAR(point.x, expected[4].x, 0.1);
2562 EXPECT_NEAR(point.y, expected[4].y, 0.1);
2563 }

References impeller::HostBuffer::Create(), impeller::kPointArenaSize, impeller::PathBuilder::LineTo(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [375/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GiantStrokePathAllocation |
| ) |  |

Definition at line 2452 of file entity_unittests.cc.

2452 {
2453 PathBuilder builder{};
2454 for (int i = 0; i < 10000; i++) {
2455 builder.LineTo(Point(i, i));
2456 }
2457 Path path = builder.TakePath();
2458 auto geom = Geometry::MakeStrokePath(path, /*stroke_width=*/10);
2459
2460 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2461 Entity entity;
2462
2463 auto cmd_buffer = content_context.GetContext()->CreateCommandBuffer();
2464
2465 RenderTargetAllocator allocator(
2466 content_context.GetContext()->GetResourceAllocator());
2467
2468 auto render_target = allocator.CreateOffscreen(
2469 *content_context.GetContext(), /*size=*/{10, 10}, /*mip_count=*/1);
2470 auto pass = cmd_buffer->CreateRenderPass(render_target);
2471
2472 GeometryResult result =
2473 geom->GetPositionBuffer(content_context, entity, *pass);
2474
2475 // Validate the buffer data overflowed the small buffer
2476 EXPECT_GT(result.vertex_buffer.vertex_count, kPointArenaSize);
2477
2478 // Validate that there are no uninitialized points near the gap.
2479 Point* written_data = reinterpret_cast<Point*>(
2480 (result.vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2481 result.vertex_buffer.vertex_buffer.GetRange().offset));
2482
2483 std::vector<Point> expected = {
2484 Point(1019.46, 1026.54), //
2485 Point(1026.54, 1019.46), //
2486 Point(1020.45, 1027.54), //
2487 Point(1027.54, 1020.46), //
2488 Point(1020.46, 1027.53) //
2489 };
2490
2491 Point point = written_data[kPointArenaSize - 2];
2492 EXPECT_NEAR(point.x, expected[0].x, 0.1);
2493 EXPECT_NEAR(point.y, expected[0].y, 0.1);
2494
2495 point = written_data[kPointArenaSize - 1];
2496 EXPECT_NEAR(point.x, expected[1].x, 0.1);
2497 EXPECT_NEAR(point.y, expected[1].y, 0.1);
2498
2499 point = written_data[kPointArenaSize];
2500 EXPECT_NEAR(point.x, expected[2].x, 0.1);
2501 EXPECT_NEAR(point.y, expected[2].y, 0.1);
2502
2503 point = written_data[kPointArenaSize + 1];
2504 EXPECT_NEAR(point.x, expected[3].x, 0.1);
2505 EXPECT_NEAR(point.y, expected[3].y, 0.1);
2506
2507 point = written_data[kPointArenaSize + 2];
2508 EXPECT_NEAR(point.x, expected[4].x, 0.1);
2509 EXPECT_NEAR(point.y, expected[4].y, 0.1);
2510 }

References impeller::RenderTargetAllocator::CreateOffscreen(), impeller::BufferView::GetBuffer(), impeller::ContentContext::GetContext(), impeller::BufferView::GetRange(), impeller::kPointArenaSize, impeller::PathBuilder::LineTo(), impeller::Geometry::MakeStrokePath(), impeller::Range::offset, impeller::DeviceBuffer::OnGetContents(), impeller::VertexBuffer::vertex_buffer, impeller::GeometryResult::vertex_buffer, impeller::VertexBuffer::vertex_count, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [376/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2001 of file entity_unittests.cc.

2001 {
2002 Matrix matrix;
2003 LinearGradientContents contents;
2004 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2005 contents.SetGeometry(geom.get());
2006
2007 contents.SetColors({Color::CornflowerBlue()});
2008 EXPECT_TRUE(contents.IsOpaque(matrix));
2009 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2010 EXPECT_FALSE(contents.IsOpaque(matrix));
2011 contents.SetColors({Color::CornflowerBlue()});
2012 contents.SetTileMode(Entity::TileMode::kDecal);
2013 EXPECT_FALSE(contents.IsOpaque(matrix));
2014
2015 // Create stroked path that required alpha coverage.
2016 geom = Geometry::MakeStrokePath(
2017 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2018 /*stroke_width=*/0.05);
2019 contents.SetGeometry(geom.get());
2020 contents.SetColors({Color::CornflowerBlue()});
2021
2022 EXPECT_FALSE(contents.IsOpaque(matrix));
2023 }

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() [377/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1495 of file entity_unittests.cc.

1495 {
1496 auto image = CreateTextureForFixture("kalimba.jpg");
1497 ASSERT_TRUE(image);
1498
1499 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1500 auto filtered =
1501 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1502
1503 // Define the entity that will serve as the control image as a Gaussian blur
1504 // filter with no filter at all.
1505 Entity entity_left;
1506 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1507 Matrix::MakeTranslation({100, 300}) *
1508 Matrix::MakeScale(Vector2{0.5, 0.5}));
1509 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1510 Sigma{0}, Sigma{0});
1511 entity_left.SetContents(unfiltered);
1512
1513 // Define the entity that will be filtered from linear to sRGB.
1514 Entity entity_right;
1515 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1516 Matrix::MakeTranslation({500, 300}) *
1517 Matrix::MakeScale(Vector2{0.5, 0.5}));
1518 entity_right.SetContents(filtered);
1519 return entity_left.Render(context, pass) &&
1520 entity_right.Render(context, pass);
1521 };
1522
1523 ASSERT_TRUE(OpenPlaygroundHere(callback));
1524 }

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() [378/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1473 of file entity_unittests.cc.

1473 {
1474 // Set up a simple color background.
1475 auto geom = Geometry::MakeFillPath(
1476 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1477 auto fill = std::make_shared<SolidColorContents>();
1478 fill->SetGeometry(geom.get());
1479 fill->SetColor(Color::MintCream());
1480
1481 auto filter =
1482 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1483
1484 Entity e;
1485 e.SetTransform(Matrix());
1486
1487 // Confirm that the actual filter coverage matches the expected coverage.
1488 auto actual = filter->GetCoverage(e);
1489 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1490
1491 ASSERT_TRUE(actual.has_value());
1492 ASSERT_RECT_NEAR(actual.value(), expected);
1493 }

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() [379/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1081 of file entity_unittests.cc.

1081 {
1082 auto boston = CreateTextureForFixture("boston.jpg");
1083 ASSERT_TRUE(boston);
1084
1085 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1086 const char* morphology_type_names[] = {"Dilate", "Erode"};
1087 const FilterContents::MorphType morphology_types[] = {
1088 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1089 static Color input_color = Color::Black();
1090 // UI state.
1091 static int selected_morphology_type = 0;
1092 static float radius[2] = {20, 20};
1093 static Color cover_color(1, 0, 0, 0.2);
1094 static Color bounds_color(0, 1, 0, 0.1);
1095 static float offset[2] = {500, 400};
1096 static float rotation = 0;
1097 static float scale[2] = {0.65, 0.65};
1098 static float skew[2] = {0, 0};
1099 static float path_rect[4] = {0, 0,
1100 static_cast<float>(boston->GetSize().width),
1101 static_cast<float>(boston->GetSize().height)};
1102 static float effect_transform_scale = 1;
1103
1104 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1105 {
1106 ImGui::Combo("Morphology type", &selected_morphology_type,
1107 morphology_type_names,
1108 sizeof(morphology_type_names) / sizeof(char*));
1109 ImGui::SliderFloat2("Radius", radius, 0, 200);
1110 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1111 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1112 ImGui::ColorEdit4("Bounds color ",
1113 reinterpret_cast<float*>(&bounds_color));
1114 ImGui::SliderFloat2("Translation", offset, 0,
1115 pass.GetRenderTargetSize().width);
1116 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1117 ImGui::SliderFloat2("Scale", scale, 0, 3);
1118 ImGui::SliderFloat2("Skew", skew, -3, 3);
1119 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1120 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1121 3);
1122 }
1123 ImGui::End();
1124
1125 std::shared_ptr<Contents> input;
1126 Size input_size;
1127
1128 auto input_rect =
1129 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1130 auto texture = std::make_shared<TextureContents>();
1131 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1132 texture->SetDestinationRect(input_rect);
1133 texture->SetTexture(boston);
1134 texture->SetOpacity(input_color.alpha);
1135
1136 input = texture;
1137 input_size = input_rect.GetSize();
1138
1139 auto contents = FilterContents::MakeMorphology(
1140 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1141 morphology_types[selected_morphology_type]);
1142 contents->SetEffectTransform(Matrix::MakeScale(
1143 Vector2{effect_transform_scale, effect_transform_scale}));
1144
1145 auto ctm = Matrix::MakeScale(GetContentScale()) *
1146 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1147 Matrix::MakeRotationZ(Radians(rotation)) *
1148 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1149 Matrix::MakeSkew(skew[0], skew[1]) *
1150 Matrix::MakeTranslation(-Point(input_size) / 2);
1151
1152 Entity entity;
1153 entity.SetContents(contents);
1154 entity.SetTransform(ctm);
1155
1156 entity.Render(context, pass);
1157
1158 // Renders a red "cover" rectangle that shows the original position of the
1159 // unfiltered input.
1160 Entity cover_entity;
1161 std::unique_ptr<Geometry> geom =
1162 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1163 auto cover_contents = std::make_shared<SolidColorContents>();
1164 cover_contents->SetColor(cover_color);
1165 cover_contents->SetGeometry(geom.get());
1166 cover_entity.SetContents(cover_contents);
1167 cover_entity.SetTransform(ctm);
1168 cover_entity.Render(context, pass);
1169
1170 // Renders a green bounding rect of the target filter.
1171 Entity bounds_entity;
1172 std::unique_ptr<Geometry> bounds_geom = Geometry::MakeFillPath(
1173 PathBuilder{}
1174 .AddRect(contents->GetCoverage(entity).value())
1175 .TakePath());
1176 auto bounds_contents = std::make_shared<SolidColorContents>();
1177 bounds_contents->SetColor(bounds_color);
1178 bounds_contents->SetGeometry(bounds_geom.get());
1179 bounds_entity.SetContents(std::move(bounds_contents));
1180 bounds_entity.SetTransform(Matrix());
1181
1182 bounds_entity.Render(context, pass);
1183
1184 return true;
1185 };
1186 ASSERT_TRUE(OpenPlaygroundHere(callback));
1187 }

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() [380/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2084 of file entity_unittests.cc.

2084 {
2085 std::vector<Point> points = {{10, 20}, {100, 200}};
2086 PointFieldGeometry geometry(points.data(), 2, 5.0, false);
2087 ASSERT_EQ(geometry.GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2088 ASSERT_EQ(geometry.GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2089 Rect::MakeLTRB(35, 15, 135, 205));
2090 }

References impeller::PointFieldGeometry::GetCoverage(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [381/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2025 of file entity_unittests.cc.

2025 {
2026 Matrix matrix;
2027 RadialGradientContents contents;
2028 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2029 contents.SetGeometry(geom.get());
2030
2031 contents.SetColors({Color::CornflowerBlue()});
2032 EXPECT_TRUE(contents.IsOpaque(matrix));
2033 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2034 EXPECT_FALSE(contents.IsOpaque(matrix));
2035 contents.SetColors({Color::CornflowerBlue()});
2036 contents.SetTileMode(Entity::TileMode::kDecal);
2037 EXPECT_FALSE(contents.IsOpaque(matrix));
2038
2039 // Create stroked path that required alpha coverage.
2040 geom = Geometry::MakeStrokePath(
2041 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2042 /*stroke_width=*/0.05);
2043 contents.SetGeometry(geom.get());
2044 contents.SetColors({Color::CornflowerBlue()});
2045
2046 EXPECT_FALSE(contents.IsOpaque(matrix));
2047 }

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() [382/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1332 of file entity_unittests.cc.

1332 {
1333 auto callback = [&](ContentContext& context, RenderPass& pass) {
1334 static Color color = Color::Red();
1335 static float corner_radius = 100;
1336 static float blur_radius = 100;
1337 static bool show_coverage = false;
1338 static Color coverage_color = Color::Green().WithAlpha(0.2);
1339
1340 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1341 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1342 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1343 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1344 ImGui::Checkbox("Show coverage", &show_coverage);
1345 if (show_coverage) {
1346 ImGui::ColorEdit4("Coverage color",
1347 reinterpret_cast<Scalar*>(&coverage_color));
1348 }
1349 ImGui::End();
1350
1351 PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1352 PlaygroundPoint bottom_right_point(Point(600, 400), 30, Color::White());
1353 auto [top_left, bottom_right] =
1354 DrawPlaygroundLine(top_left_point, bottom_right_point);
1355 auto rect =
1356 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1357
1358 auto contents = std::make_unique<SolidRRectBlurContents>();
1359 contents->SetRRect(rect, {corner_radius, corner_radius});
1360 contents->SetColor(color);
1361 contents->SetSigma(Radius(blur_radius));
1362
1363 Entity entity;
1364 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1365 entity.SetContents(std::move(contents));
1366 entity.Render(context, pass);
1367
1368 auto coverage = entity.GetCoverage();
1369 if (show_coverage && coverage.has_value()) {
1370 auto bounds_contents = std::make_unique<SolidColorContents>();
1371 auto geom = Geometry::MakeFillPath(
1372 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
1373 bounds_contents->SetGeometry(geom.get());
1374 bounds_contents->SetColor(coverage_color.Premultiply());
1375 Entity bounds_entity;
1376 bounds_entity.SetContents(std::move(bounds_contents));
1377 bounds_entity.Render(context, pass);
1378 }
1379
1380 return true;
1381 };
1382 ASSERT_TRUE(OpenPlaygroundHere(callback));
1383 }

References impeller::PathBuilder::AddRect(), blur_radius, 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() [383/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 1691 of file entity_unittests.cc.

1691 {
1692 auto runtime_stages =
1693 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1694 auto runtime_stage =
1695 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1696 ASSERT_TRUE(runtime_stage);
1697 ASSERT_TRUE(runtime_stage->IsDirty());
1698
1699 bool expect_dirty = true;
1700
1701 PipelineRef first_pipeline;
1702 std::unique_ptr<Geometry> geom = Geometry::MakeCover();
1703
1704 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1705 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1706
1707 auto contents = std::make_shared<RuntimeEffectContents>();
1708 contents->SetGeometry(geom.get());
1709 contents->SetRuntimeStage(runtime_stage);
1710
1711 struct FragUniforms {
1712 Vector2 iResolution;
1713 Scalar iTime;
1714 } frag_uniforms = {
1715 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1716 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1717 };
1718 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1719 uniform_data->resize(sizeof(FragUniforms));
1720 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1721 contents->SetUniformData(uniform_data);
1722
1723 Entity entity;
1724 entity.SetContents(contents);
1725 bool result = contents->Render(context, entity, pass);
1726
1727 if (expect_dirty) {
1728 first_pipeline = pass.GetCommands().back().pipeline;
1729 } else {
1730 EXPECT_EQ(pass.GetCommands().back().pipeline, first_pipeline);
1731 }
1732 expect_dirty = false;
1733 return result;
1734 };
1735
1736 // Simulate some renders and hot reloading of the shader.
1737 auto content_context = GetContentContext();
1738 {
1739 RenderTarget target =
1740 content_context->GetRenderTargetCache()->CreateOffscreen(
1741 *content_context->GetContext(), {1, 1}, 1u);
1742
1743 testing::MockRenderPass mock_pass(GetContext(), target);
1744 callback(*content_context, mock_pass);
1745 callback(*content_context, mock_pass);
1746
1747 // Dirty the runtime stage.
1748 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1749 runtime_stage =
1750 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1751
1752 ASSERT_TRUE(runtime_stage->IsDirty());
1753 expect_dirty = true;
1754
1755 callback(*content_context, mock_pass);
1756 }
1757 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [384/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanPrecache |
| ) |  |

Definition at line 1806 of file entity_unittests.cc.

1806 {
1807 auto runtime_stages =
1808 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1809 auto runtime_stage =
1810 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1811 ASSERT_TRUE(runtime_stage);
1812 ASSERT_TRUE(runtime_stage->IsDirty());
1813
1814 auto contents = std::make_shared<RuntimeEffectContents>();
1815 contents->SetRuntimeStage(runtime_stage);
1816
1817 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
1818 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [385/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 1759 of file entity_unittests.cc.

1759 {
1760 auto runtime_stages =
1761 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1762 auto runtime_stage =
1763 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1764 ASSERT_TRUE(runtime_stage);
1765 ASSERT_TRUE(runtime_stage->IsDirty());
1766
1767 auto contents = std::make_shared<RuntimeEffectContents>();
1768 auto geom = Geometry::MakeCover();
1769 contents->SetGeometry(geom.get());
1770 contents->SetRuntimeStage(runtime_stage);
1771
1772 struct FragUniforms {
1773 Vector2 iResolution;
1774 Scalar iTime;
1775 } frag_uniforms = {
1776 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1777 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1778 };
1779 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1780 uniform_data->resize(sizeof(FragUniforms));
1781 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1782 contents->SetUniformData(uniform_data);
1783
1784 Entity entity;
1785 entity.SetContents(contents);
1786
1787 // Create a render target with a depth-stencil, similar to how EntityPass
1788 // does.
1789 RenderTarget target =
1790 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
1791 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
1792 "RuntimeEffect Texture");
1793 testing::MockRenderPass pass(GetContext(), target);
1794
1795 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
1796 ASSERT_EQ(pass.GetCommands().size(), 1u);
1797 const auto& command = pass.GetCommands()[0];
1798 ASSERT_TRUE(command.pipeline->GetDescriptor()
1799 .GetDepthStencilAttachmentDescriptor()
1800 .has_value());
1801 ASSERT_TRUE(command.pipeline->GetDescriptor()
1802 .GetFrontStencilAttachmentDescriptor()
1803 .has_value());
1804 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [386/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 1820 of file entity_unittests.cc.

1820 {
1821 if (GetBackend() != PlaygroundBackend::kVulkan) {
1822 GTEST_SKIP() << "Test only applies to Vulkan";
1823 }
1824
1825 auto runtime_stages =
1826 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1827 auto runtime_stage =
1828 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1829 ASSERT_TRUE(runtime_stage);
1830 ASSERT_TRUE(runtime_stage->IsDirty());
1831
1832 auto contents = std::make_shared<RuntimeEffectContents>();
1833 auto geom = Geometry::MakeCover();
1834 contents->SetGeometry(geom.get());
1835 contents->SetRuntimeStage(runtime_stage);
1836
1837 struct FragUniforms {
1838 Vector2 iResolution;
1839 Scalar iTime;
1840 } frag_uniforms = {
1841 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1842 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1843 };
1844 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1845 uniform_data->resize(sizeof(FragUniforms));
1846 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1847
1848 auto buffer_view = RuntimeEffectContents::EmplaceVulkanUniform(
1849 uniform_data, GetContentContext()->GetTransientsBuffer(),
1850 runtime_stage->GetUniforms()[0]);
1851
1852 // 16 bytes:
1853 // 8 bytes for iResolution
1854 // 4 bytes for iTime
1855 // 4 bytes padding
1856 EXPECT_EQ(buffer_view.GetRange().length, 16u);
1857 }

References buffer_view, impeller::RuntimeEffectContents::EmplaceVulkanUniform(), impeller::kVulkan, impeller::Geometry::MakeCover(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [387/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1189 of file entity_unittests.cc.

1189 {
1190 Entity entity;
1191 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSourceOver);
1192 entity.SetBlendMode(BlendMode::kClear);
1193 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1194 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSourceOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [388/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorApplyColorFilter |
| ) |  |

Definition at line 2422 of file entity_unittests.cc.

2422 {
2423 auto contents = SolidColorContents();
2424 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2425 auto result = contents.ApplyColorFilter([](const Color& color) {
2426 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2427 });
2428 ASSERT_TRUE(result);
2429 ASSERT_COLOR_NEAR(contents.GetColor(),
2430 Color(0.424452, 0.828743, 0.79105, 0.9375));
2431 }

References ASSERT_COLOR_NEAR, impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [389/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 1959 of file entity_unittests.cc.

1959 {
1960 Matrix matrix;
1961 SolidColorContents contents;
1962 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
1963 contents.SetGeometry(geom.get());
1964
1965 contents.SetColor(Color::CornflowerBlue());
1966 EXPECT_TRUE(contents.IsOpaque(matrix));
1967 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
1968 EXPECT_FALSE(contents.IsOpaque(matrix));
1969
1970 // Create stroked path that required alpha coverage.
1971 geom = Geometry::MakeStrokePath(
1972 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
1973 /*stroke_width=*/0.05);
1974 contents.SetGeometry(geom.get());
1975 contents.SetColor(Color::CornflowerBlue());
1976
1977 EXPECT_FALSE(contents.IsOpaque(matrix));
1978 }

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() [390/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 676 of file entity_unittests.cc.

676 {
677 {
678 auto geometry = Geometry::MakeStrokePath(Path{});
679 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
680 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
681 }
682
683 {
684 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0,
685 /*miter_limit=*/8.0);
686 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
687 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
688 }
689
690 {
691 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0,
692 /*miter_limit=*/-1.0);
693 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
694 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
695 }
696 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [391/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 654 of file entity_unittests.cc.

654 {
655 {
656 auto geometry = Geometry::MakeStrokePath(Path{});
657 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
658 // Defaults.
659 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
660 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
661 }
662
663 {
664 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
665 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
666 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
667 }
668
669 {
670 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
671 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
672 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
673 }
674 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [392/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1286 of file entity_unittests.cc.

1286 {
1287 // No transform
1288 {
1289 auto fill = std::make_shared<SolidColorContents>();
1290 fill->SetColor(Color::CornflowerBlue());
1291 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1292 auto geom =
1293 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath());
1294 fill->SetGeometry(geom.get());
1295
1296 auto coverage = fill->GetCoverage({});
1297 ASSERT_TRUE(coverage.has_value());
1298 ASSERT_RECT_NEAR(coverage.value(), expected);
1299 }
1300
1301 // Entity transform
1302 {
1303 auto fill = std::make_shared<SolidColorContents>();
1304 auto geom = Geometry::MakeFillPath(
1305 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
1306 fill->SetColor(Color::CornflowerBlue());
1307 fill->SetGeometry(geom.get());
1308
1309 Entity entity;
1310 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1311 entity.SetContents(std::move(fill));
1312
1313 auto coverage = entity.GetCoverage();
1314 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1315 ASSERT_TRUE(coverage.has_value());
1316 ASSERT_RECT_NEAR(coverage.value(), expected);
1317 }
1318
1319 // No coverage for fully transparent colors
1320 {
1321 auto fill = std::make_shared<SolidColorContents>();
1322 auto geom = Geometry::MakeFillPath(
1323 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
1324 fill->SetColor(Color::WhiteTransparent());
1325 fill->SetGeometry(geom.get());
1326
1327 auto coverage = fill->GetCoverage({});
1328 ASSERT_FALSE(coverage.has_value());
1329 }
1330 }

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() [393/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1202 of file entity_unittests.cc.

1202 {
1203 {
1204 auto geometry = Geometry::MakeStrokePath(
1205 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1206 Cap::kButt, Join::kBevel);
1207
1208 Entity entity;
1209 auto contents = std::make_unique<SolidColorContents>();
1210 contents->SetGeometry(geometry.get());
1211 contents->SetColor(Color::Black());
1212 entity.SetContents(std::move(contents));
1213 auto actual = entity.GetCoverage();
1214 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1215
1216 ASSERT_TRUE(actual.has_value());
1217 ASSERT_RECT_NEAR(actual.value(), expected);
1218 }
1219
1220 // Cover the Cap::kSquare case.
1221 {
1222 auto geometry = Geometry::MakeStrokePath(
1223 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1224 Cap::kSquare, Join::kBevel);
1225
1226 Entity entity;
1227 auto contents = std::make_unique<SolidColorContents>();
1228 contents->SetGeometry(geometry.get());
1229 contents->SetColor(Color::Black());
1230 entity.SetContents(std::move(contents));
1231 auto actual = entity.GetCoverage();
1232 auto expected =
1233 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1234
1235 ASSERT_TRUE(actual.has_value());
1236 ASSERT_RECT_NEAR(actual.value(), expected);
1237 }
1238
1239 // Cover the Join::kMiter case.
1240 {
1241 auto geometry = Geometry::MakeStrokePath(
1242 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1243 Cap::kSquare, Join::kMiter);
1244
1245 Entity entity;
1246 auto contents = std::make_unique<SolidColorContents>();
1247 contents->SetGeometry(geometry.get());
1248 contents->SetColor(Color::Black());
1249 entity.SetContents(std::move(contents));
1250 auto actual = entity.GetCoverage();
1251 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1252
1253 ASSERT_TRUE(actual.has_value());
1254 ASSERT_RECT_NEAR(actual.value(), expected);
1255 }
1256 }

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() [394/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2120 of file entity_unittests.cc.

2120 {
2121 auto content_context = GetContentContext();
2122
2123 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2124 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2125 .has_depth_stencil_attachments = false,
2126 });
2127 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2128 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2129 .has_depth_stencil_attachments = true});
2130
2131 EXPECT_NE(default_gyph, alt_gyph);
2132 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2133 alt_gyph->GetDescriptor().GetSpecializationConstants());
2134
2135 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2136 PixelFormat::kA8UNormInt;
2137
2138 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2139 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2140 expected_constants);
2141 }

References impeller::kA8UNormInt, and impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [395/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1548 of file entity_unittests.cc.

1548 {
1549 auto image = CreateTextureForFixture("embarcadero.jpg");
1550 ASSERT_TRUE(image);
1551
1552 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1553 auto filtered =
1554 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1555
1556 // Define the entity that will serve as the control image as a Gaussian blur
1557 // filter with no filter at all.
1558 Entity entity_left;
1559 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1560 Matrix::MakeTranslation({100, 300}) *
1561 Matrix::MakeScale(Vector2{0.5, 0.5}));
1562 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1563 Sigma{0}, Sigma{0});
1564 entity_left.SetContents(unfiltered);
1565
1566 // Define the entity that will be filtered from sRGB to linear.
1567 Entity entity_right;
1568 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1569 Matrix::MakeTranslation({500, 300}) *
1570 Matrix::MakeScale(Vector2{0.5, 0.5}));
1571 entity_right.SetContents(filtered);
1572 return entity_left.Render(context, pass) &&
1573 entity_right.Render(context, pass);
1574 };
1575
1576 ASSERT_TRUE(OpenPlaygroundHere(callback));
1577 }

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() [396/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1526 of file entity_unittests.cc.

1526 {
1527 // Set up a simple color background.
1528 auto fill = std::make_shared<SolidColorContents>();
1529 auto geom = Geometry::MakeFillPath(
1530 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1531 fill->SetGeometry(geom.get());
1532 fill->SetColor(Color::DeepPink());
1533
1534 auto filter =
1535 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1536
1537 Entity e;
1538 e.SetTransform(Matrix());
1539
1540 // Confirm that the actual filter coverage matches the expected coverage.
1541 auto actual = filter->GetCoverage(e);
1542 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1543
1544 ASSERT_TRUE(actual.has_value());
1545 ASSERT_RECT_NEAR(actual.value(), expected);
1546 }

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() [397/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 196 of file entity_unittests.cc.

196 {
197 const Point padding(300, 250);
198 const Point margin(140, 180);
199
200 auto callback = [&](ContentContext& context, RenderPass& pass) {
201 // Slightly above sqrt(2) by default, so that right angles are just below
202 // the limit and acute angles are over the limit (causing them to get
203 // beveled).
204 static Scalar miter_limit = 1.41421357;
205 static Scalar width = 30;
206
207 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
208 {
209 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
210 ImGui::SliderFloat("Stroke width", &width, 0, 100);
211 if (ImGui::Button("Reset")) {
212 miter_limit = 1.41421357;
213 width = 30;
214 }
215 }
216 ImGui::End();
217
218 auto world_matrix = Matrix::MakeScale(GetContentScale());
219 auto render_path = [width = width, &context, &pass, &world_matrix](
220 const Path& path, Cap cap, Join join) {
221 auto contents = std::make_unique<SolidColorContents>();
222 std::unique_ptr<Geometry> geom =
223 Geometry::MakeStrokePath(path, width, miter_limit, cap, join);
224 contents->SetGeometry(geom.get());
225 contents->SetColor(Color::Red());
226
227 Entity entity;
228 entity.SetTransform(world_matrix);
229 entity.SetContents(std::move(contents));
230
231 auto coverage = entity.GetCoverage();
232 if (coverage.has_value()) {
233 auto bounds_contents = std::make_unique<SolidColorContents>();
234
235 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
236 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
237
238 bounds_contents->SetGeometry(geom.get());
239 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
240 Entity bounds_entity;
241 bounds_entity.SetContents(std::move(bounds_contents));
242 bounds_entity.Render(context, pass);
243 }
244
245 entity.Render(context, pass);
246 };
247
248 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
249 e_def(75, 75);
250 const Scalar r = 30;
251 // Cap::kButt demo.
252 {
253 Point off = Point(0, 0) * padding + margin;
254 PlaygroundPoint point_a(off + a_def, r, Color::Black());
255 PlaygroundPoint point_b(off + b_def, r, Color::White());
256 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
257 PlaygroundPoint point_c(off + c_def, r, Color::Black());
258 PlaygroundPoint point_d(off + d_def, r, Color::White());
259 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
260 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
261 Cap::kButt, Join::kBevel);
262 }
263
264 // Cap::kSquare demo.
265 {
266 Point off = Point(1, 0) * padding + margin;
267 PlaygroundPoint point_a(off + a_def, r, Color::Black());
268 PlaygroundPoint point_b(off + b_def, r, Color::White());
269 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
270 PlaygroundPoint point_c(off + c_def, r, Color::Black());
271 PlaygroundPoint point_d(off + d_def, r, Color::White());
272 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
273 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
274 Cap::kSquare, Join::kBevel);
275 }
276
277 // Cap::kRound demo.
278 {
279 Point off = Point(2, 0) * padding + margin;
280 PlaygroundPoint point_a(off + a_def, r, Color::Black());
281 PlaygroundPoint point_b(off + b_def, r, Color::White());
282 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
283 PlaygroundPoint point_c(off + c_def, r, Color::Black());
284 PlaygroundPoint point_d(off + d_def, r, Color::White());
285 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
286 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
287 Cap::kRound, Join::kBevel);
288 }
289
290 // Join::kBevel demo.
291 {
292 Point off = Point(0, 1) * padding + margin;
293 PlaygroundPoint point_a = PlaygroundPoint(off + a_def, r, Color::White());
294 PlaygroundPoint point_b = PlaygroundPoint(off + e_def, r, Color::White());
295 PlaygroundPoint point_c = PlaygroundPoint(off + c_def, r, Color::White());
296 Point a = DrawPlaygroundPoint(point_a);
297 Point b = DrawPlaygroundPoint(point_b);
298 Point c = DrawPlaygroundPoint(point_c);
299 render_path(
300 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
301 Cap::kButt, Join::kBevel);
302 }
303
304 // Join::kMiter demo.
305 {
306 Point off = Point(1, 1) * padding + margin;
307 PlaygroundPoint point_a(off + a_def, r, Color::White());
308 PlaygroundPoint point_b(off + e_def, r, Color::White());
309 PlaygroundPoint point_c(off + c_def, r, Color::White());
310 Point a = DrawPlaygroundPoint(point_a);
311 Point b = DrawPlaygroundPoint(point_b);
312 Point c = DrawPlaygroundPoint(point_c);
313 render_path(
314 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
315 Cap::kButt, Join::kMiter);
316 }
317
318 // Join::kRound demo.
319 {
320 Point off = Point(2, 1) * padding + margin;
321 PlaygroundPoint point_a(off + a_def, r, Color::White());
322 PlaygroundPoint point_b(off + e_def, r, Color::White());
323 PlaygroundPoint point_c(off + c_def, r, Color::White());
324 Point a = DrawPlaygroundPoint(point_a);
325 Point b = DrawPlaygroundPoint(point_b);
326 Point c = DrawPlaygroundPoint(point_c);
327 render_path(
328 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
329 Cap::kButt, Join::kRound);
330 }
331
332 return true;
333 };
334 ASSERT_TRUE(OpenPlaygroundHere(callback));
335 }

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() [398/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 131 of file entity_unittests.cc.

131 {
132 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
133 Path path = PathBuilder{}
134 .MoveTo({100, 100})
135 .LineTo({100, 200})
136 .MoveTo({100, 300})
137 .LineTo({100, 400})
138 .MoveTo({100, 500})
139 .LineTo({100, 600})
140 .TakePath();
141
142 Entity entity;
143 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
144 auto contents = std::make_unique<TiledTextureContents>();
145 std::unique_ptr<Geometry> geom = Geometry::MakeStrokePath(path, 100.0);
146 contents->SetGeometry(geom.get());
147 contents->SetTexture(bridge);
148 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
149 entity.SetContents(std::move(contents));
150 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
151 }

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() [399/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2049 of file entity_unittests.cc.

2049 {
2050 Matrix matrix;
2051 RadialGradientContents contents;
2052 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2053 contents.SetGeometry(geom.get());
2054
2055 contents.SetColors({Color::CornflowerBlue()});
2056 EXPECT_TRUE(contents.IsOpaque(matrix));
2057 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2058 EXPECT_FALSE(contents.IsOpaque(matrix));
2059 contents.SetColors({Color::CornflowerBlue()});
2060 contents.SetTileMode(Entity::TileMode::kDecal);
2061 EXPECT_FALSE(contents.IsOpaque(matrix));
2062
2063 // Create stroked path that required alpha coverage.
2064 geom = Geometry::MakeStrokePath(
2065 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2066 /*stroke_width=*/0.05);
2067 contents.SetGeometry(geom.get());
2068 contents.SetColors({Color::CornflowerBlue()});
2069
2070 EXPECT_FALSE(contents.IsOpaque(matrix));
2071 }

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() [400/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2112 of file entity_unittests.cc.

2112 {
2113 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f), 0.43f);
2114 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f), 0.53f);
2115 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f), 2.1f);
2116 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f), 0.0f);
2117 ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f), 48.0f);
2118 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [401/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 110 of file entity_unittests.cc.

110 {
111 Path path = PathBuilder{}
112 .MoveTo({100, 100})
113 .LineTo({100, 200})
114 .MoveTo({100, 300})
115 .LineTo({100, 400})
116 .MoveTo({100, 500})
117 .LineTo({100, 600})
118 .TakePath();
119
120 Entity entity;
121 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
122 auto contents = std::make_unique<SolidColorContents>();
123
124 std::unique_ptr<Geometry> geom = Geometry::MakeStrokePath(path, 5.0);
125 contents->SetGeometry(geom.get());
126 contents->SetColor(Color::Red());
127 entity.SetContents(std::move(contents));
128 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
129 }

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() [402/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2073 of file entity_unittests.cc.

2073 {
2074 Matrix matrix;
2075 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2076 TiledTextureContents contents;
2077 contents.SetTexture(bay_bridge);
2078 // This is a placeholder test. Images currently never decompress as opaque
2079 // (whether in Flutter or the playground), and so this should currently always
2080 // return false in practice.
2081 EXPECT_FALSE(contents.IsOpaque(matrix));
2082 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [403/494]

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() [404/494]

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() [405/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 153 of file entity_unittests.cc.

153 {
154 auto callback = [&](ContentContext& context, RenderPass& pass) {
155 Point offset(100, 100);
156
157 PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
158 Point a = DrawPlaygroundPoint(point_a);
159 PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
160 Point b = DrawPlaygroundPoint(point_b);
161 PlaygroundPoint point_c(Point(210, 210) + offset, 20, Color::White());
162 Point c = DrawPlaygroundPoint(point_c);
163 PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
164 Point d = DrawPlaygroundPoint(point_d);
165 PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
166 Point e = DrawPlaygroundPoint(point_e);
167 PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
168 Point f = DrawPlaygroundPoint(point_f);
169 PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
170 Point g = DrawPlaygroundPoint(point_g);
171 Path path = PathBuilder{}
172 .MoveTo(a)
173 .LineTo(b)
174 .LineTo(c)
175 .LineTo(d)
176 .Close()
177 .MoveTo(e)
178 .LineTo(f)
179 .LineTo(g)
180 .Close()
181 .TakePath();
182
183 Entity entity;
184 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
185 auto contents = std::make_unique<SolidColorContents>();
186 std::unique_ptr<Geometry> geom = Geometry::MakeStrokePath(path, 20.0);
187 contents->SetGeometry(geom.get());
188 contents->SetColor(Color::Red());
189 entity.SetContents(std::move(contents));
190
191 return entity.Render(context, pass);
192 };
193 ASSERT_TRUE(OpenPlaygroundHere(callback));
194 }

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() [406/494]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 1657 of file entity_unittests.cc.

1657 {
1658 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1659 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
1660 GTEST_SKIP()
1661 << "YUV to RGB filter is not supported on OpenGLES backend yet.";
1662 }
1663
1664 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1665 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
1666 YUVColorSpace::kBT601LimitedRange};
1667 for (int i = 0; i < 2; i++) {
1668 auto yuv_color_space = yuv_color_space_array[i];
1669 auto textures =
1670 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
1671 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
1672 textures[0], textures[1], yuv_color_space);
1673 Entity filter_entity;
1674 filter_entity.SetContents(filter_contents);
1675 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
1676
1677 Entity entity;
1678 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
1679 contents->SetTexture(snapshot->texture);
1680 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
1681 entity.SetContents(contents);
1682 entity.SetTransform(
1683 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
1684 entity.Render(context, pass);
1685 }
1686 return true;
1687 };
1688 ASSERT_TRUE(OpenPlaygroundHere(callback));
1689 }

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() [407/494]

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() [408/494]

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() [409/494]

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() [410/494]

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() [411/494]

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() [412/494]

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() [413/494]

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() [414/494]

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() [415/494]

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() [416/494]

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

Definition at line 36 of file host_buffer_unittests.cc.

36 {
37 struct Length2 {
38 uint8_t pad[2];
39 };
40 static_assert(sizeof(Length2) == 2u);
41
42 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
43 GetContext()->GetIdleWaiter());
44
45 for (size_t i = 0; i < 12500; i++) {
46 auto view = buffer->Emplace(Length2{});
47 ASSERT_TRUE(view);
48 ASSERT_EQ(view.GetRange(), Range(i * sizeof(Length2), 2u));
49 }
50 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [417/494]

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

Definition at line 52 of file host_buffer_unittests.cc.

52 {
53 struct Length2 {
54 uint8_t pad[2];
55 };
56 static_assert(sizeof(Length2) == 2);
57 struct alignas(16) Align16 {
58 uint8_t pad[2];
59 };
60 static_assert(alignof(Align16) == 16);
61 static_assert(sizeof(Align16) == 16);
62
63 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
64 GetContext()->GetIdleWaiter());
65 ASSERT_TRUE(buffer);
66
67 {
68 auto view = buffer->Emplace(Length2{});
69 ASSERT_TRUE(view);
70 ASSERT_EQ(view.GetRange(), Range(0u, 2u));
71 }
72
73 {
74 auto view = buffer->Emplace(Align16{});
75 ASSERT_TRUE(view);
76 ASSERT_EQ(view.GetRange().offset, 16u);
77 ASSERT_EQ(view.GetRange().length, 16u);
78 }
79 {
80 auto view = buffer->Emplace(Length2{});
81 ASSERT_TRUE(view);
82 ASSERT_EQ(view.GetRange(), Range(32u, 2u));
83 }
84
85 {
86 auto view = buffer->Emplace(Align16{});
87 ASSERT_TRUE(view);
88 ASSERT_EQ(view.GetRange().offset, 48u);
89 ASSERT_EQ(view.GetRange().length, 16u);
90 }
91 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [418/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithFailingAllocationDoesntCrash |
| ) |  |

Definition at line 221 of file host_buffer_unittests.cc.

221 {
222 ScopedValidationDisable disable;
223 std::shared_ptr<FailingAllocator> allocator =
224 std::make_shared<FailingAllocator>(GetContext()->GetResourceAllocator());
225 auto buffer = HostBuffer::Create(allocator, GetContext()->GetIdleWaiter());
226
227 auto view = buffer->Emplace(nullptr, kMagicFailingAllocation, 0);
228
229 EXPECT_EQ(view.GetBuffer(), nullptr);
230 EXPECT_EQ(view.GetRange().offset, 0u);
231 EXPECT_EQ(view.GetRange().length, 0u);
232 }

References impeller::HostBuffer::Create(), and kMagicFailingAllocation.

## ◆ TEST_P() [419/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithProcIsAligned |
| ) |  |

Definition at line 180 of file host_buffer_unittests.cc.

180 {
181 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
182 GetContext()->GetIdleWaiter());
183
184 BufferView view = buffer->Emplace(std::array<char, 21>());
185 EXPECT_EQ(view.GetRange(), Range(0, 21));
186
187 view = buffer->Emplace(64, 16, [](uint8_t*) {});
188 EXPECT_EQ(view.GetRange(), Range(32, 64));
189 }

References impeller::HostBuffer::Create(), and impeller::BufferView::GetRange().

## ◆ TEST_P() [420/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBuffer |
| ) |  |

Definition at line 135 of file host_buffer_unittests.cc.

135 {
136 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
137 GetContext()->GetIdleWaiter());
138
139 // Emplace an amount larger than the block size, to verify that the host
140 // buffer does not create a buffer.
141 auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0);
142
143 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
144 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
145 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
146 }

References buffer_view, and impeller::HostBuffer::Create().

## ◆ TEST_P() [421/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback |
| ) |  |

Definition at line 121 of file host_buffer_unittests.cc.

122 {
123 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
124 GetContext()->GetIdleWaiter());
125
126 // Emplace an amount larger than the block size, to verify that the host
127 // buffer does not create a buffer.
128 auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {});
129
130 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
131 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
132 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
133 }

References buffer_view, impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [422/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | HostBufferInitialState |
| ) |  |

Definition at line 93 of file host_buffer_unittests.cc.

93 {
94 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
95 GetContext()->GetIdleWaiter());
96
97 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
98 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
99 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
100 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [423/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | IdleWaiter |
| ) |  |

Definition at line 27 of file host_buffer_unittests.cc.

27 {
28 auto mock_idle_waiter = std::make_shared<MockIdleWaiter>();
29 {
30 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
31 mock_idle_waiter);
32 EXPECT_CALL(*mock_idle_waiter, WaitIdle());
33 }
34 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [424/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | ResetIncrementsFrameCounter |
| ) |  |

Definition at line 102 of file host_buffer_unittests.cc.

102 {
103 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
104 GetContext()->GetIdleWaiter());
105
106 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
107
108 buffer->Reset();
109 EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u);
110
111 buffer->Reset();
112 EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u);
113
114 buffer->Reset();
115 EXPECT_EQ(buffer->GetStateForTest().current_frame, 3u);
116
117 buffer->Reset();
118 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
119 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [425/494]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | UnusedBuffersAreDiscardedWhenResetting |
| ) |  |

Definition at line 148 of file host_buffer_unittests.cc.

148 {
149 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
150 GetContext()->GetIdleWaiter());
151
152 // Emplace two large allocations to force the allocation of a second buffer.
153 auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
154 auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
155
156 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u);
157 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
158 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
159
160 // Reset until we get back to this frame.
161 for (auto i = 0; i < 4; i++) {
162 buffer->Reset();
163 }
164
165 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
166 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
167 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
168
169 // Now when we reset, the buffer should get dropped.
170 // Reset until we get back to this frame.
171 for (auto i = 0; i < 4; i++) {
172 buffer->Reset();
173 }
174
175 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
176 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
177 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
178 }

References impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [426/494]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageClippedSubpassScale |
| ) |  |

Definition at line 175 of file matrix_filter_contents_unittests.cc.

176 {
177 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
178 MatrixFilterContents contents;
179 contents.SetInputs({FilterInput::Make(texture)});
180 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
181 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
182 contents.SetRenderingMode(
183 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
184
185 Entity entity;
186 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
187
188 std::shared_ptr<ContentContext> renderer = GetContentContext();
189 std::optional<Entity> result =
190 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
191 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
192 Rect::MakeXYWH(100, 200, 300, 300));
193 }

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() [427/494]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageClippedSubpassTranslate |
| ) |  |

Definition at line 138 of file matrix_filter_contents_unittests.cc.

139 {
140 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
141 MatrixFilterContents contents;
142 contents.SetInputs({FilterInput::Make(texture)});
143 contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
144 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
145 contents.SetRenderingMode(
146 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
147
148 Entity entity;
149 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
150
151 std::shared_ptr<ContentContext> renderer = GetContentContext();
152 std::optional<Entity> result =
153 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
154 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
155 Rect::MakeXYWH(200, 400, 100, 100));
156 }

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() [428/494]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageIdentity |
| ) |  |

Definition at line 106 of file matrix_filter_contents_unittests.cc.

106 {
107 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
108 MatrixFilterContents contents;
109 contents.SetInputs({FilterInput::Make(texture)});
110
111 Entity entity;
112 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
113
114 std::shared_ptr<ContentContext> renderer = GetContentContext();
115 std::optional<Entity> result =
116 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
117 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
118 Rect::MakeXYWH(100, 200, 100, 100));
119 }

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() [429/494]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageScale |
| ) |  |

Definition at line 158 of file matrix_filter_contents_unittests.cc.

158 {
159 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
160 MatrixFilterContents contents;
161 contents.SetInputs({FilterInput::Make(texture)});
162 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
163 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
164
165 Entity entity;
166 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
167
168 std::shared_ptr<ContentContext> renderer = GetContentContext();
169 std::optional<Entity> result =
170 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
171 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
172 Rect::MakeXYWH(100, 200, 300, 300));
173 }

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() [430/494]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageSubpassScale |
| ) |  |

Definition at line 195 of file matrix_filter_contents_unittests.cc.

195 {
196 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
197 MatrixFilterContents contents;
198 contents.SetInputs({FilterInput::Make(texture)});
199 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
200 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
201 contents.SetRenderingMode(
202 Entity::RenderingMode::kSubpassPrependSnapshotTransform);
203
204 Entity entity;
205 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
206
207 std::shared_ptr<ContentContext> renderer = GetContentContext();
208 std::optional<Entity> result =
209 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
210 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
211 Rect::MakeXYWH(300, 600, 300, 300));
212 }

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() [431/494]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 121 of file matrix_filter_contents_unittests.cc.

121 {
122 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
123 MatrixFilterContents contents;
124 contents.SetInputs({FilterInput::Make(texture)});
125 contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
126 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
127
128 Entity entity;
129 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
130
131 std::shared_ptr<ContentContext> renderer = GetContentContext();
132 std::optional<Entity> result =
133 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
134 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
135 Rect::MakeXYWH(150, 300, 100, 100));
136 }

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() [432/494]

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() [433/494]

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() [434/494]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateRenderPassAndSubmit |
| ) |  |

Definition at line 299 of file renderer_dart_unittests.cc.

299 {
300 ASSERT_TRUE(RenderDartToPlayground("canCreateRenderPassAndSubmit"));
301 }

## ◆ TEST_P() [435/494]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateShaderLibrary |
| ) |  |

Definition at line 291 of file renderer_dart_unittests.cc.

291 {
292 ASSERT_TRUE(RunDartFunction("canCreateShaderLibrary"));
293 }

## ◆ TEST_P() [436/494]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanInstantiateFlutterGPUContext |
| ) |  |

These test entries correspond to Dart functions located in `flutter/impeller/fixtures/dart_tests.dart`

Definition at line 287 of file renderer_dart_unittests.cc.

287 {
288 ASSERT_TRUE(RunDartFunction("instantiateDefaultContext"));
289 }

## ◆ TEST_P() [437/494]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanReflectUniformStructs |
| ) |  |

Definition at line 295 of file renderer_dart_unittests.cc.

295 {
296 ASSERT_TRUE(RunDartFunction("canReflectUniformStructs"));
297 }

## ◆ TEST_P() [438/494]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanRunDartInPlaygroundFrame |
| ) |  |

Definition at line 272 of file renderer_dart_unittests.cc.

272 {
273 SinglePassCallback callback = [&](RenderPass& pass) {
274 ImGui::Begin("Dart test", nullptr);
275 ImGui::Text(
276 "This test executes Dart code during the playground frame callback.");
277 ImGui::End();
278
279 return RunDartFunction("sayHi");
280 };
281 ASSERT_TRUE(OpenPlaygroundHere(callback));
282 }

## ◆ TEST_P() [439/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 1017 of file renderer_unittests.cc.

1017 {
1018 using VS = ArrayVertexShader;
1019 using FS = ArrayFragmentShader;
1020
1021 auto context = GetContext();
1022 auto pipeline_descriptor =
1023 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1024 ASSERT_TRUE(pipeline_descriptor.has_value());
1025 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1026 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1027 auto pipeline =
1028 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1029 ASSERT_TRUE(pipeline && pipeline->IsValid());
1030
1031 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
1032 context->GetIdleWaiter());
1033 SinglePassCallback callback = [&](RenderPass& pass) {
1034 auto size = pass.GetRenderTargetSize();
1035
1036 pass.SetPipeline(pipeline);
1037 pass.SetCommandLabel("Google Dots");
1038 VertexBufferBuilder<VS::PerVertexData> builder;
1039 builder.AddVertices({{Point()},
1040 {Point(0, size.height)},
1041 {Point(size.width, 0)},
1042 {Point(size.width, 0)},
1043 {Point(0, size.height)},
1044 {Point(size.width, size.height)}});
1045 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1046
1047 VS::FrameInfo frame_info;
1048 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1049 frame_info.mvp =
1050 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1051 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1052
1053 auto time = GetSecondsElapsed();
1054 auto y_pos = [&time](float x) {
1055 return 400 + 10 * std::cos(time * 5 + x / 6);
1056 };
1057
1058 FS::FragInfo fs_uniform = {
1059 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
1060 Point(530, y_pos(2)), Point(580, y_pos(3))},
1061 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
1062 Color::MakeRGBA8(219, 68, 55, 255),
1063 Color::MakeRGBA8(244, 180, 0, 255),
1064 Color::MakeRGBA8(15, 157, 88, 255)},
1065 };
1066 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1067
1068 pass.Draw();
1069 host_buffer->Reset();
1070 return true;
1071 };
1072 OpenPlaygroundHere(callback);
1073 }

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(), impeller::Matrix::MakeScale(), and x.

## ◆ TEST_P() [440/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BabysFirstTriangle |
| ) |  |

Definition at line 122 of file renderer_unittests.cc.

122 {
123 auto context = GetContext();
124 ASSERT_TRUE(context);
125
126 // Declare a shorthand for the shaders we are going to use.
127 using VS = BabyVertexShader;
128 using FS = BabyFragmentShader;
129
130 // Create a pipeline descriptor that uses the shaders together and default
131 // initializes the fixed function state.
132 //
133 // If the vertex shader outputs disagree with the fragment shader inputs, this
134 // will be a compile time error.
135 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
136 ASSERT_TRUE(desc.has_value());
137
138 // Modify the descriptor for our environment. This is specific to our test.
139 desc->SetSampleCount(SampleCount::kCount4);
140 desc->SetStencilAttachmentDescriptors(std::nullopt);
141
142 // Create a pipeline from our descriptor. This is expensive to do. So just do
143 // it once.
144 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
145
146 // Create a host side buffer to build the vertex and uniform information.
147 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
148 context->GetIdleWaiter());
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 context->GetIdleWaiter());
170 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
171
172 return pass.Draw().ok();
173 };
174 OpenPlaygroundHere(callback);
175 }

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() [441/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BindingNullTexturesDoesNotCrash |
| ) |  |

Definition at line 1613 of file renderer_unittests.cc.

1613 {
1614 using FS = BoxFadeFragmentShader;
1615
1616 auto context = GetContext();
1617 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1618 auto command_buffer = context->CreateCommandBuffer();
1619
1620 RenderTargetAllocator allocator(context->GetResourceAllocator());
1621 RenderTarget target = allocator.CreateOffscreen(*context, {1, 1}, 1);
1622
1623 auto pass = command_buffer->CreateRenderPass(target);
1624 EXPECT_FALSE(FS::BindContents2(*pass, nullptr, sampler));
1625 }

References impeller::RenderTargetAllocator::CreateOffscreen().

## ◆ TEST_P() [442/494]

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 = render_target.GetColorAttachment(0).resolve_texture;
27 auto& texture_vk = TextureVK::Cast(*resolve_texture);
28
29 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), nullptr);
30 EXPECT_EQ(texture_vk.GetCachedRenderPass(), nullptr);
31
32 auto buffer = GetContext()->CreateCommandBuffer();
33 auto render_pass = buffer->CreateRenderPass(render_target);
34
35 EXPECT_NE(texture_vk.GetCachedFramebuffer(), nullptr);
36 EXPECT_NE(texture_vk.GetCachedRenderPass(), nullptr);
37
38 render_pass->EncodeCommands();
39 GetContext()->GetCommandQueue()->Submit({buffer});
40
41 // Can be reused without error.
42 auto buffer_2 = GetContext()->CreateCommandBuffer();
43 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
44
45 EXPECT_TRUE(render_pass_2->EncodeCommands());
46 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
47 }

References impeller::BackendCast< TextureVK, Texture >::Cast(), and impeller::kVulkan.

## ◆ TEST_P() [443/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 634 of file renderer_unittests.cc.

634 {
635 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
636 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
637 }
638 auto context = GetContext();
639 ASSERT_TRUE(context);
640
641 using VS = MipmapsVertexShader;
642 using FS = MipmapsFragmentShader;
643 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
644 ASSERT_TRUE(desc.has_value());
645 desc->SetSampleCount(SampleCount::kCount4);
646 desc->SetStencilAttachmentDescriptors(std::nullopt);
647 auto mipmaps_pipeline =
648 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
649 ASSERT_TRUE(mipmaps_pipeline);
650
651 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
652 auto boston = CreateTextureForFixture("boston.jpg");
653 ASSERT_TRUE(bridge && boston);
654 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
655 ASSERT_TRUE(sampler);
656
657 TextureDescriptor texture_desc;
658 texture_desc.storage_mode = StorageMode::kHostVisible;
659 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
660 texture_desc.size = bridge->GetTextureDescriptor().size;
661 texture_desc.mip_count = 1u;
662 texture_desc.usage = TextureUsage::kRenderTarget |
663 TextureUsage::kShaderWrite | TextureUsage::kShaderRead;
664 DeviceBufferDescriptor device_buffer_desc;
665 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
666 device_buffer_desc.size =
667 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
668 auto device_buffer =
669 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
670
671 // Vertex buffer.
672 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
673 vertex_builder.SetLabel("Box");
674 auto size = Point(boston->GetSize());
675 vertex_builder.AddVertices({
676 {{0, 0}, {0.0, 0.0}}, // 1
677 {{size.x, 0}, {1.0, 0.0}}, // 2
678 {{size.x, size.y}, {1.0, 1.0}}, // 3
679 {{0, 0}, {0.0, 0.0}}, // 1
680 {{size.x, size.y}, {1.0, 1.0}}, // 3
681 {{0, size.y}, {0.0, 1.0}}, // 4
682 });
683 auto vertex_buffer =
684 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
685 ASSERT_TRUE(vertex_buffer);
686
687 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
688 context->GetIdleWaiter());
689 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
690 {
691 auto buffer = context->CreateCommandBuffer();
692 if (!buffer) {
693 return false;
694 }
695 buffer->SetLabel("Playground Command Buffer");
696 auto pass = buffer->CreateBlitPass();
697 if (!pass) {
698 return false;
699 }
700 pass->SetLabel("Playground Blit Pass");
701
702 // Blit `bridge` to the top left corner of the texture.
703 pass->AddCopy(bridge, device_buffer);
704 pass->EncodeCommands();
705
706 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
707 return false;
708 }
709 }
710
711 {
712 auto buffer = context->CreateCommandBuffer();
713 if (!buffer) {
714 return false;
715 }
716 buffer->SetLabel("Playground Command Buffer");
717
718 auto pass = buffer->CreateRenderPass(render_target);
719 if (!pass) {
720 return false;
721 }
722 pass->SetLabel("Playground Render Pass");
723 {
724 pass->SetCommandLabel("Image");
725 pass->SetPipeline(mipmaps_pipeline);
726 pass->SetVertexBuffer(vertex_buffer);
727
728 VS::FrameInfo frame_info;
729 EXPECT_EQ(pass->GetOrthographicTransform(),
730 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
731 frame_info.mvp = pass->GetOrthographicTransform() *
732 Matrix::MakeScale(GetContentScale());
733 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
734
735 FS::FragInfo frag_info;
736 frag_info.lod = 0;
737 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
738
739 raw_ptr<const Sampler> sampler =
740 context->GetSamplerLibrary()->GetSampler({});
741 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
742 auto texture =
743 context->GetResourceAllocator()->CreateTexture(texture_desc);
744 if (!texture->SetContents(device_buffer->OnGetContents(),
745 buffer_view.GetRange().length)) {
746 VALIDATION_LOG << "Could not upload texture to device memory";
747 return false;
748 }
749 FS::BindTex(*pass, texture, sampler);
750
751 pass->Draw().ok();
752 }
753 pass->EncodeCommands();
754 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
755 return false;
756 }
757 }
758 host_buffer->Reset();
759 return true;
760 };
761 OpenPlaygroundHere(callback);
762 }

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() [444/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 523 of file renderer_unittests.cc.

523 {
524 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
525 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
526 }
527 auto context = GetContext();
528 ASSERT_TRUE(context);
529
530 using VS = MipmapsVertexShader;
531 using FS = MipmapsFragmentShader;
532 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
533 ASSERT_TRUE(desc.has_value());
534 desc->SetSampleCount(SampleCount::kCount4);
535 desc->SetStencilAttachmentDescriptors(std::nullopt);
536 auto mipmaps_pipeline =
537 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
538 ASSERT_TRUE(mipmaps_pipeline);
539
540 TextureDescriptor texture_desc;
541 texture_desc.storage_mode = StorageMode::kHostVisible;
542 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
543 texture_desc.size = {800, 600};
544 texture_desc.mip_count = 1u;
545 texture_desc.usage = TextureUsage::kRenderTarget | TextureUsage::kShaderRead;
546 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
547 ASSERT_TRUE(texture);
548
549 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
550 auto boston = CreateTextureForFixture("boston.jpg");
551 ASSERT_TRUE(bridge && boston);
552 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
553 ASSERT_TRUE(sampler);
554
555 // Vertex buffer.
556 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
557 vertex_builder.SetLabel("Box");
558 auto size = Point(boston->GetSize());
559 vertex_builder.AddVertices({
560 {{0, 0}, {0.0, 0.0}}, // 1
561 {{size.x, 0}, {1.0, 0.0}}, // 2
562 {{size.x, size.y}, {1.0, 1.0}}, // 3
563 {{0, 0}, {0.0, 0.0}}, // 1
564 {{size.x, size.y}, {1.0, 1.0}}, // 3
565 {{0, size.y}, {0.0, 1.0}}, // 4
566 });
567 auto vertex_buffer =
568 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
569 ASSERT_TRUE(vertex_buffer);
570
571 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
572 context->GetIdleWaiter());
573 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
574 auto buffer = context->CreateCommandBuffer();
575 if (!buffer) {
576 return false;
577 }
578 buffer->SetLabel("Playground Command Buffer");
579
580 {
581 auto pass = buffer->CreateBlitPass();
582 if (!pass) {
583 return false;
584 }
585 pass->SetLabel("Playground Blit Pass");
586
587 // Blit `bridge` to the top left corner of the texture.
588 pass->AddCopy(bridge, texture);
589
590 if (!pass->EncodeCommands()) {
591 return false;
592 }
593 }
594
595 {
596 auto pass = buffer->CreateRenderPass(render_target);
597 if (!pass) {
598 return false;
599 }
600 pass->SetLabel("Playground Render Pass");
601 {
602 pass->SetCommandLabel("Image");
603 pass->SetPipeline(mipmaps_pipeline);
604 pass->SetVertexBuffer(vertex_buffer);
605
606 VS::FrameInfo frame_info;
607 EXPECT_EQ(pass->GetOrthographicTransform(),
608 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
609 frame_info.mvp = pass->GetOrthographicTransform() *
610 Matrix::MakeScale(GetContentScale());
611 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
612
613 FS::FragInfo frag_info;
614 frag_info.lod = 0;
615 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
616
617 auto sampler = context->GetSamplerLibrary()->GetSampler({});
618 FS::BindTex(*pass, texture, sampler);
619
620 pass->Draw();
621 }
622 pass->EncodeCommands();
623 }
624
625 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
626 return false;
627 }
628 host_buffer->Reset();
629 return true;
630 };
631 OpenPlaygroundHere(callback);
632 }

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() [445/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateBoxPrimitive |
| ) |  |

Definition at line 53 of file renderer_unittests.cc.

53 {
54 using VS = BoxFadeVertexShader;
55 using FS = BoxFadeFragmentShader;
56 auto context = GetContext();
57 ASSERT_TRUE(context);
58 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
59 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
60 ASSERT_TRUE(desc.has_value());
61 desc->SetSampleCount(SampleCount::kCount4);
62 desc->SetStencilAttachmentDescriptors(std::nullopt);
63
64 // Vertex buffer.
65 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
66 vertex_builder.SetLabel("Box");
67 vertex_builder.AddVertices({
68 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
69 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
70 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
71 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
72 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
73 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
74 });
75 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
76 auto boston = CreateTextureForFixture("boston.jpg");
77 ASSERT_TRUE(bridge && boston);
78 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
79 ASSERT_TRUE(sampler);
80
81 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
82 context->GetIdleWaiter());
83 SinglePassCallback callback = [&](RenderPass& pass) {
84 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
85 static bool wireframe;
86 ImGui::Checkbox("Wireframe", &wireframe);
87 ImGui::End();
88
89 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
90 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
91
92 assert(pipeline && pipeline->IsValid());
93
94 pass.SetCommandLabel("Box");
95 pass.SetPipeline(pipeline);
96 pass.SetVertexBuffer(
97 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
98
99 VS::UniformBuffer uniforms;
100 EXPECT_EQ(pass.GetOrthographicTransform(),
101 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
102 uniforms.mvp =
103 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
104 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
105
106 FS::FrameInfo frame_info;
107 frame_info.current_time = GetSecondsElapsed();
108 frame_info.cursor_position = GetCursorPosition();
109 frame_info.window_size.x = GetWindowSize().width;
110 frame_info.window_size.y = GetWindowSize().height;
111
112 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
113 FS::BindContents1(pass, boston, sampler);
114 FS::BindContents2(pass, bridge, sampler);
115
116 host_buffer->Reset();
117 return pass.Draw().ok();
118 };
119 OpenPlaygroundHere(callback);
120 }

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() [446/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 764 of file renderer_unittests.cc.

764 {
765 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
766 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
767 }
768 auto context = GetContext();
769 ASSERT_TRUE(context);
770
771 using VS = MipmapsVertexShader;
772 using FS = MipmapsFragmentShader;
773 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
774 ASSERT_TRUE(desc.has_value());
775 desc->SetSampleCount(SampleCount::kCount4);
776 desc->SetStencilAttachmentDescriptors(std::nullopt);
777 auto mipmaps_pipeline =
778 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
779 ASSERT_TRUE(mipmaps_pipeline);
780
781 auto boston = CreateTextureForFixture("boston.jpg", true);
782 ASSERT_TRUE(boston);
783
784 // Vertex buffer.
785 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
786 vertex_builder.SetLabel("Box");
787 auto size = Point(boston->GetSize());
788 vertex_builder.AddVertices({
789 {{0, 0}, {0.0, 0.0}}, // 1
790 {{size.x, 0}, {1.0, 0.0}}, // 2
791 {{size.x, size.y}, {1.0, 1.0}}, // 3
792 {{0, 0}, {0.0, 0.0}}, // 1
793 {{size.x, size.y}, {1.0, 1.0}}, // 3
794 {{0, size.y}, {0.0, 1.0}}, // 4
795 });
796 auto vertex_buffer =
797 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
798 ASSERT_TRUE(vertex_buffer);
799
800 bool first_frame = true;
801 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
802 context->GetIdleWaiter());
803 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
804 const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
805 const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
806 MipFilter::kLinear};
807 const char* min_filter_names[] = {"Nearest", "Linear"};
808 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
809 MinMagFilter::kLinear};
810
811 // UI state.
812 static int selected_mip_filter = 1;
813 static int selected_min_filter = 0;
814 static float lod = 4.5;
815
816 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
817 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
818 sizeof(mip_filter_names) / sizeof(char*));
819 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
820 sizeof(min_filter_names) / sizeof(char*));
821 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
822 ImGui::End();
823
824 auto buffer = context->CreateCommandBuffer();
825 if (!buffer) {
826 return false;
827 }
828 buffer->SetLabel("Playground Command Buffer");
829
830 if (first_frame) {
831 auto pass = buffer->CreateBlitPass();
832 if (!pass) {
833 return false;
834 }
835 pass->SetLabel("Playground Blit Pass");
836
837 pass->GenerateMipmap(boston, "Boston Mipmap");
838
839 pass->EncodeCommands();
840 }
841
842 first_frame = false;
843
844 {
845 auto pass = buffer->CreateRenderPass(render_target);
846 if (!pass) {
847 return false;
848 }
849 pass->SetLabel("Playground Render Pass");
850 {
851 pass->SetCommandLabel("Image LOD");
852 pass->SetPipeline(mipmaps_pipeline);
853 pass->SetVertexBuffer(vertex_buffer);
854
855 VS::FrameInfo frame_info;
856 EXPECT_EQ(pass->GetOrthographicTransform(),
857 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
858 frame_info.mvp = pass->GetOrthographicTransform() *
859 Matrix::MakeScale(GetContentScale());
860 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
861
862 FS::FragInfo frag_info;
863 frag_info.lod = lod;
864 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
865
866 SamplerDescriptor sampler_desc;
867 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
868 sampler_desc.min_filter = min_filters[selected_min_filter];
869 raw_ptr<const Sampler> sampler =
870 context->GetSamplerLibrary()->GetSampler(sampler_desc);
871 FS::BindTex(*pass, boston, sampler);
872
873 pass->Draw();
874 }
875 pass->EncodeCommands();
876 }
877
878 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
879 return false;
880 }
881 host_buffer->Reset();
882 return true;
883 };
884 OpenPlaygroundHere(callback);
885 }

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() [447/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanLookupRenderTargetProperties |
| ) |  |

Definition at line 1363 of file renderer_unittests.cc.

1363 {
1364 auto context = GetContext();
1365 auto cmd_buffer = context->CreateCommandBuffer();
1366 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1367 GetContext()->GetResourceAllocator());
1368
1369 auto render_target = render_target_cache->CreateOffscreen(
1370 *context, {100, 100}, /*mip_count=*/1);
1371 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1372
1373 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1374 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1375 render_target.GetRenderTargetPixelFormat());
1376 EXPECT_EQ(render_pass->HasStencilAttachment(),
1377 render_target.GetStencilAttachment().has_value());
1378 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1379 render_target.GetRenderTargetSize());
1380 render_pass->EncodeCommands();
1381 }

## ◆ TEST_P() [448/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 465 of file renderer_unittests.cc.

465 {
466 if (GetParam() == PlaygroundBackend::kOpenGLES) {
467 GTEST_SKIP() << "Instancing is not supported on OpenGL.";
468 }
469 using VS = InstancedDrawVertexShader;
470 using FS = InstancedDrawFragmentShader;
471
472 VertexBufferBuilder<VS::PerVertexData> builder;
473 builder.AddVertices({
474 VS::PerVertexData{Point{10, 10}},
475 VS::PerVertexData{Point{10, 110}},
476 VS::PerVertexData{Point{110, 10}},
477 VS::PerVertexData{Point{10, 110}},
478 VS::PerVertexData{Point{110, 10}},
479 VS::PerVertexData{Point{110, 110}},
480 });
481
482 ASSERT_NE(GetContext(), nullptr);
483 auto pipeline =
484 GetContext()
485 ->GetPipelineLibrary()
486 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
487 *GetContext())
488 ->SetSampleCount(SampleCount::kCount4)
489 .SetStencilAttachmentDescriptors(std::nullopt))
490
491 .Get();
492 ASSERT_TRUE(pipeline && pipeline->IsValid());
493
494 static constexpr size_t kInstancesCount = 5u;
495 VS::InstanceInfo<kInstancesCount> instances;
496 for (size_t i = 0; i < kInstancesCount; i++) {
497 instances.colors[i] = Color::Random();
498 }
499
500 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
501 GetContext()->GetIdleWaiter());
502 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
503 pass.SetPipeline(pipeline);
504 pass.SetCommandLabel("InstancedDraw");
505
506 VS::FrameInfo frame_info;
507 EXPECT_EQ(pass.GetOrthographicTransform(),
508 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
509 frame_info.mvp =
510 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
511 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
512 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
513 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
514
515 pass.SetInstanceCount(kInstancesCount);
516 pass.Draw();
517
518 host_buffer->Reset();
519 return true;
520 }));
521 }

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() [449/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 289 of file renderer_unittests.cc.

289 {
290 using VS = BoxFadeVertexShader;
291 using FS = BoxFadeFragmentShader;
292 auto context = GetContext();
293 ASSERT_TRUE(context);
294 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
295 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
296 ASSERT_TRUE(desc.has_value());
297 desc->SetSampleCount(SampleCount::kCount4);
298 desc->SetStencilAttachmentDescriptors(std::nullopt);
299 auto box_pipeline =
300 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
301 ASSERT_TRUE(box_pipeline);
302
303 // Vertex buffer.
304 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
305 vertex_builder.SetLabel("Box");
306 vertex_builder.AddVertices({
307 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
308 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
309 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
310 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
311 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
312 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
313 });
314 auto vertex_buffer =
315 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
316 ASSERT_TRUE(vertex_buffer);
317
318 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
319 auto boston = CreateTextureForFixture("boston.jpg");
320 ASSERT_TRUE(bridge && boston);
321 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
322 ASSERT_TRUE(sampler);
323
324 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
325 context->GetIdleWaiter());
326 SinglePassCallback callback = [&](RenderPass& pass) {
327 for (size_t i = 0; i < 1; i++) {
328 for (size_t j = 0; j < 1; j++) {
329 pass.SetCommandLabel("Box");
330 pass.SetPipeline(box_pipeline);
331 pass.SetVertexBuffer(vertex_buffer);
332
333 FS::FrameInfo frame_info;
334 frame_info.current_time = GetSecondsElapsed();
335 frame_info.cursor_position = GetCursorPosition();
336 frame_info.window_size.x = GetWindowSize().width;
337 frame_info.window_size.y = GetWindowSize().height;
338
339 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
340 FS::BindContents1(pass, boston, sampler);
341 FS::BindContents2(pass, bridge, sampler);
342
343 VS::UniformBuffer uniforms;
344 EXPECT_EQ(pass.GetOrthographicTransform(),
345 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
346 uniforms.mvp = pass.GetOrthographicTransform() *
347 Matrix::MakeScale(GetContentScale()) *
348 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
349 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
350 if (!pass.Draw().ok()) {
351 return false;
352 }
353 }
354 }
355
356 host_buffer->Reset();
357 return true;
358 };
359 OpenPlaygroundHere(callback);
360 }

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() [450/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 177 of file renderer_unittests.cc.

177 {
178 using VS = ColorsVertexShader;
179 using FS = ColorsFragmentShader;
180 auto context = GetContext();
181 ASSERT_TRUE(context);
182 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
183 ASSERT_TRUE(desc.has_value());
184 desc->SetCullMode(CullMode::kBackFace);
185 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
186 desc->SetSampleCount(SampleCount::kCount4);
187 desc->ClearStencilAttachments();
188
189 // Setup the vertex layout to take two bindings. The first for positions and
190 // the second for colors.
191 auto vertex_desc = std::make_shared<VertexDescriptor>();
192 ShaderStageIOSlot position_slot = VS::kInputPosition;
193 ShaderStageIOSlot color_slot = VS::kInputColor;
194 position_slot.binding = 0;
195 position_slot.offset = 0;
196 color_slot.binding = 1;
197 color_slot.offset = 0;
198 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
199 const std::vector<ShaderStageBufferLayout> layouts = {
200 ShaderStageBufferLayout{.stride = 12u, .binding = 0},
201 ShaderStageBufferLayout{.stride = 16u, .binding = 1}};
202 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
203 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
204 vertex_desc->SetStageInputs(io_slots, layouts);
205 desc->SetVertexDescriptor(std::move(vertex_desc));
206 auto pipeline =
207 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
208 ASSERT_TRUE(pipeline);
209
210 struct Cube {
211 Vector3 positions[8] = {
212 // -Z
213 {-1, -1, -1},
214 {1, -1, -1},
215 {1, 1, -1},
216 {-1, 1, -1},
217 // +Z
218 {-1, -1, 1},
219 {1, -1, 1},
220 {1, 1, 1},
221 {-1, 1, 1},
222 };
223 Color colors[8] = {
224 Color::Red(), Color::Yellow(), Color::Green(), Color::Blue(),
225 Color::Green(), Color::Blue(), Color::Red(), Color::Yellow(),
226 };
227 uint16_t indices[36] = {
228 1, 5, 2, 2, 5, 6, // +X
229 4, 0, 7, 7, 0, 3, // -X
230 4, 5, 0, 0, 5, 1, // +Y
231 3, 2, 7, 7, 2, 6, // -Y
232 5, 4, 6, 6, 4, 7, // +Z
233 0, 1, 3, 3, 1, 2, // -Z
234 };
235 } cube;
236
237 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
238 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
239
240 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
241 ASSERT_TRUE(sampler);
242
243 Vector3 euler_angles;
244 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
245 context->GetIdleWaiter());
246 SinglePassCallback callback = [&](RenderPass& pass) {
247 static Degrees fov_y(60);
248 static Scalar distance = 10;
249
250 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
251 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
252 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
253 ImGui::End();
254
255 pass.SetCommandLabel("Perspective Cube");
256 pass.SetPipeline(pipeline);
257
258 std::array<BufferView, 2> vertex_buffers = {
259 BufferView(device_buffer,
260 Range(offsetof(Cube, positions), sizeof(Cube::positions))),
261 BufferView(device_buffer,
262 Range(offsetof(Cube, colors), sizeof(Cube::colors))),
263 };
264
265 BufferView index_buffer(
266 device_buffer, Range(offsetof(Cube, indices), sizeof(Cube::indices)));
267 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
268 pass.SetElementCount(36);
269 pass.SetIndexBuffer(index_buffer, IndexType::k16bit);
270
271 VS::UniformBuffer uniforms;
272 Scalar time = GetSecondsElapsed();
273 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
274
275 uniforms.mvp =
276 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
277 Matrix::MakeTranslation({0, 0, distance}) *
278 Matrix::MakeRotationX(Radians(euler_angles.x)) *
279 Matrix::MakeRotationY(Radians(euler_angles.y)) *
280 Matrix::MakeRotationZ(Radians(euler_angles.z));
281 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
282
283 host_buffer->Reset();
284 return pass.Draw().ok();
285 };
286 OpenPlaygroundHere(callback);
287 }

References impeller::ShaderStageIOSlot::binding, impeller::Color::Blue(), impeller::HostBuffer::Create(), impeller::Degrees::degrees, impeller::saturated::distance, impeller::Color::Green(), 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::ShaderStageIOSlot::offset, impeller::Color::Red(), impeller::ShaderStageBufferLayout::stride, impeller::Vector3::x, impeller::Vector3::y, impeller::Color::Yellow(), and impeller::Vector3::z.

## ◆ TEST_P() [451/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 362 of file renderer_unittests.cc.

362 {
363 using VS = BoxFadeVertexShader;
364 using FS = BoxFadeFragmentShader;
365 auto context = GetContext();
366 ASSERT_TRUE(context);
367 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
368 auto pipeline_desc =
369 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
370 pipeline_desc->SetSampleCount(SampleCount::kCount1);
371 pipeline_desc->ClearDepthAttachment();
372 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
373
374 ASSERT_TRUE(pipeline_desc.has_value());
375 auto box_pipeline =
376 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
377 ASSERT_TRUE(box_pipeline);
378 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
379 context->GetIdleWaiter());
380
381 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
382 vertex_builder.SetLabel("Box");
383 vertex_builder.AddVertices({
384 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
385 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
386 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
387 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
388 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
389 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
390 });
391 auto vertex_buffer =
392 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
393 ASSERT_TRUE(vertex_buffer);
394
395 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
396 auto boston = CreateTextureForFixture("boston.jpg");
397 ASSERT_TRUE(bridge && boston);
398 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
399 ASSERT_TRUE(sampler);
400
401 std::shared_ptr<RenderPass> r2t_pass;
402 auto cmd_buffer = context->CreateCommandBuffer();
403 ASSERT_TRUE(cmd_buffer);
404 {
405 ColorAttachment color0;
406 color0.load_action = LoadAction::kClear;
407 color0.store_action = StoreAction::kStore;
408
409 TextureDescriptor texture_descriptor;
410 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
411 texture_descriptor.format =
412 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
413 texture_descriptor.storage_mode = StorageMode::kHostVisible;
414 texture_descriptor.size = {400, 400};
415 texture_descriptor.mip_count = 1u;
416 texture_descriptor.usage = TextureUsage::kRenderTarget;
417
418 color0.texture =
419 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
420
421 ASSERT_TRUE(color0.IsValid());
422
423 color0.texture->SetLabel("r2t_target");
424
425 StencilAttachment stencil0;
426 stencil0.load_action = LoadAction::kClear;
427 stencil0.store_action = StoreAction::kDontCare;
428 TextureDescriptor stencil_texture_desc;
429 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
430 stencil_texture_desc.size = texture_descriptor.size;
431 stencil_texture_desc.format = PixelFormat::kS8UInt;
432 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
433 stencil0.texture =
434 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
435
436 RenderTarget r2t_desc;
437 r2t_desc.SetColorAttachment(color0, 0u);
438 r2t_desc.SetStencilAttachment(stencil0);
439 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
440 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
441 }
442
443 r2t_pass->SetCommandLabel("Box");
444 r2t_pass->SetPipeline(box_pipeline);
445 r2t_pass->SetVertexBuffer(vertex_buffer);
446
447 FS::FrameInfo frame_info;
448 frame_info.current_time = GetSecondsElapsed();
449 frame_info.cursor_position = GetCursorPosition();
450 frame_info.window_size.x = GetWindowSize().width;
451 frame_info.window_size.y = GetWindowSize().height;
452
453 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
454 FS::BindContents1(*r2t_pass, boston, sampler);
455 FS::BindContents2(*r2t_pass, bridge, sampler);
456
457 VS::UniformBuffer uniforms;
458 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
459 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
460 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
461 ASSERT_TRUE(r2t_pass->Draw().ok());
462 ASSERT_TRUE(r2t_pass->EncodeCommands());
463 }

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() [452/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1505 of file renderer_unittests.cc.

1505 {
1506 // Define shader types
1507 using TextureVS = TextureVertexShader;
1508 using TextureFS = TextureFragmentShader;
1509
1510 using SwizzleVS = SepiaVertexShader;
1511 using SwizzleFS = SwizzleFragmentShader;
1512
1513 using SepiaVS = SepiaVertexShader;
1514 using SepiaFS = SepiaFragmentShader;
1515
1516 auto context = GetContext();
1517 ASSERT_TRUE(context);
1518
1519 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1520 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1521 "support it.";
1522 return;
1523 }
1524
1525 // Create pipelines.
1526 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1527 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1528 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1529
1530 ASSERT_TRUE(texture_pipeline);
1531 ASSERT_TRUE(swizzle_pipeline);
1532 ASSERT_TRUE(sepia_pipeline);
1533
1534 // Vertex buffer builders.
1535 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1536 texture_vtx_builder.AddVertices({
1537 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1538 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1539 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1540 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1541 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1542 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1543 });
1544
1545 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1546 sepia_vtx_builder.AddVertices({
1547 {{100, 100, 0.0}}, // 1
1548 {{800, 100, 0.0}}, // 2
1549 {{800, 800, 0.0}}, // 3
1550 {{100, 100, 0.0}}, // 1
1551 {{800, 800, 0.0}}, // 3
1552 {{100, 800, 0.0}}, // 4
1553 });
1554
1555 auto boston = CreateTextureForFixture("boston.jpg");
1556 ASSERT_TRUE(boston);
1557
1558 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1559 ASSERT_TRUE(sampler);
1560
1561 SinglePassCallback callback = [&](RenderPass& pass) {
1562 auto buffer = HostBuffer::Create(context->GetResourceAllocator(),
1563 context->GetIdleWaiter());
1564
1565 // Draw the texture.
1566 {
1567 pass.SetPipeline(texture_pipeline);
1568 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1569 *context->GetResourceAllocator()));
1570 TextureVS::UniformBuffer uniforms;
1571 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1572 Matrix::MakeScale(GetContentScale());
1573 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1574 TextureFS::BindTextureContents(pass, boston, sampler);
1575 if (!pass.Draw().ok()) {
1576 return false;
1577 }
1578 }
1579
1580 // Draw the sepia toner.
1581 {
1582 pass.SetPipeline(sepia_pipeline);
1583 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1584 *context->GetResourceAllocator()));
1585 SepiaVS::UniformBuffer uniforms;
1586 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1587 Matrix::MakeScale(GetContentScale());
1588 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1589 if (!pass.Draw().ok()) {
1590 return false;
1591 }
1592 }
1593
1594 // Draw the swizzle.
1595 {
1596 pass.SetPipeline(swizzle_pipeline);
1597 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1598 *context->GetResourceAllocator()));
1599 SwizzleVS::UniformBuffer uniforms;
1600 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1601 Matrix::MakeScale(GetContentScale());
1602 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1603 if (!pass.Draw().ok()) {
1604 return false;
1605 }
1606 }
1607
1608 return true;
1609 };
1610 OpenPlaygroundHere(callback);
1611 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [453/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneWithSubpasses |
| ) |  |

Definition at line 1416 of file renderer_unittests.cc.

1416 {
1417 // Define shader types
1418 using TextureVS = TextureVertexShader;
1419 using TextureFS = TextureFragmentShader;
1420
1421 using SepiaVS = SepiaVertexShader;
1422 using SepiaFS = SepiaFragmentShader;
1423
1424 auto context = GetContext();
1425 ASSERT_TRUE(context);
1426
1427 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1428 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1429 "support it.";
1430 return;
1431 }
1432
1433 // Create pipelines.
1434 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1435 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1436
1437 ASSERT_TRUE(texture_pipeline);
1438 ASSERT_TRUE(sepia_pipeline);
1439
1440 // Vertex buffer builders.
1441 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1442 texture_vtx_builder.AddVertices({
1443 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1444 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1445 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1446 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1447 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1448 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1449 });
1450
1451 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1452 sepia_vtx_builder.AddVertices({
1453 {{100, 100, 0.0}}, // 1
1454 {{800, 100, 0.0}}, // 2
1455 {{800, 800, 0.0}}, // 3
1456 {{100, 100, 0.0}}, // 1
1457 {{800, 800, 0.0}}, // 3
1458 {{100, 800, 0.0}}, // 4
1459 });
1460
1461 auto boston = CreateTextureForFixture("boston.jpg");
1462 ASSERT_TRUE(boston);
1463
1464 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1465 ASSERT_TRUE(sampler);
1466
1467 SinglePassCallback callback = [&](RenderPass& pass) {
1468 auto buffer = HostBuffer::Create(context->GetResourceAllocator(),
1469 context->GetIdleWaiter());
1470
1471 // Draw the texture.
1472 {
1473 pass.SetPipeline(texture_pipeline);
1474 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1475 *context->GetResourceAllocator()));
1476 TextureVS::UniformBuffer uniforms;
1477 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1478 Matrix::MakeScale(GetContentScale());
1479 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1480 TextureFS::BindTextureContents(pass, boston, sampler);
1481 if (!pass.Draw().ok()) {
1482 return false;
1483 }
1484 }
1485
1486 // Draw the sepia toner.
1487 {
1488 pass.SetPipeline(sepia_pipeline);
1489 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1490 *context->GetResourceAllocator()));
1491 SepiaVS::UniformBuffer uniforms;
1492 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1493 Matrix::MakeScale(GetContentScale());
1494 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1495 if (!pass.Draw().ok()) {
1496 return false;
1497 }
1498 }
1499
1500 return true;
1501 };
1502 OpenPlaygroundHere(callback);
1503 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [454/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1133 of file renderer_unittests.cc.

1133 {
1134 using VS = BoxFadeVertexShader;
1135
1136 // Do not create any index buffer if no indices were provided.
1137 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1138 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1139 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [455/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1123 of file renderer_unittests.cc.

1123 {
1124 using VS = BoxFadeVertexShader;
1125
1126 // Default to 16bit index buffer size, as this is a reasonable default and
1127 // supported on all backends without extensions.
1128 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1129 vertex_builder.AppendIndex(0u);
1130 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1131 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [456/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 1075 of file renderer_unittests.cc.

1075 {
1076 using VS = InactiveUniformsVertexShader;
1077 using FS = InactiveUniformsFragmentShader;
1078
1079 auto context = GetContext();
1080 auto pipeline_descriptor =
1081 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1082 ASSERT_TRUE(pipeline_descriptor.has_value());
1083 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1084 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1085 auto pipeline =
1086 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1087 ASSERT_TRUE(pipeline && pipeline->IsValid());
1088
1089 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
1090 context->GetIdleWaiter());
1091 SinglePassCallback callback = [&](RenderPass& pass) {
1092 auto size = pass.GetRenderTargetSize();
1093
1094 pass.SetPipeline(pipeline);
1095 pass.SetCommandLabel("Inactive Uniform");
1096
1097 VertexBufferBuilder<VS::PerVertexData> builder;
1098 builder.AddVertices({{Point()},
1099 {Point(0, size.height)},
1100 {Point(size.width, 0)},
1101 {Point(size.width, 0)},
1102 {Point(0, size.height)},
1103 {Point(size.width, size.height)}});
1104 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1105
1106 VS::FrameInfo frame_info;
1107 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1108 frame_info.mvp =
1109 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1110 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1111
1112 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
1113 .color = Color::Green()};
1114 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1115
1116 pass.Draw().ok();
1117 host_buffer->Reset();
1118 return true;
1119 };
1120 OpenPlaygroundHere(callback);
1121 }

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() [457/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | Planet |
| ) |  |

Definition at line 950 of file renderer_unittests.cc.

950 {
951 using VS = PlanetVertexShader;
952 using FS = PlanetFragmentShader;
953
954 auto context = GetContext();
955 auto pipeline_descriptor =
956 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
957 ASSERT_TRUE(pipeline_descriptor.has_value());
958 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
959 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
960 auto pipeline =
961 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
962 ASSERT_TRUE(pipeline && pipeline->IsValid());
963
964 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
965 context->GetIdleWaiter());
966
967 SinglePassCallback callback = [&](RenderPass& pass) {
968 static Scalar speed = 0.1;
969 static Scalar planet_size = 550.0;
970 static bool show_normals = false;
971 static bool show_noise = false;
972 static Scalar seed_value = 42.0;
973
974 auto size = pass.GetRenderTargetSize();
975
976 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
977 ImGui::SliderFloat("Speed", &speed, 0.0, 10.0);
978 ImGui::SliderFloat("Planet Size", &planet_size, 0.1, 1000);
979 ImGui::Checkbox("Show Normals", &show_normals);
980 ImGui::Checkbox("Show Noise", &show_noise);
981 ImGui::InputFloat("Seed Value", &seed_value);
982 ImGui::End();
983
984 pass.SetPipeline(pipeline);
985 pass.SetCommandLabel("Planet scene");
986 VertexBufferBuilder<VS::PerVertexData> builder;
987 builder.AddVertices({{Point()},
988 {Point(0, size.height)},
989 {Point(size.width, 0)},
990 {Point(size.width, 0)},
991 {Point(0, size.height)},
992 {Point(size.width, size.height)}});
993 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
994
995 VS::FrameInfo frame_info;
996 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
997 frame_info.mvp = pass.GetOrthographicTransform();
998 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
999
1000 FS::FragInfo fs_uniform;
1001 fs_uniform.resolution = Point(size);
1002 fs_uniform.time = GetSecondsElapsed();
1003 fs_uniform.speed = speed;
1004 fs_uniform.planet_size = planet_size;
1005 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
1006 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
1007 fs_uniform.seed_value = seed_value;
1008 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1009
1010 pass.Draw().ok();
1011 host_buffer->Reset();
1012 return true;
1013 };
1014 OpenPlaygroundHere(callback);
1015 }

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() [458/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat |
| ) |  |

Definition at line 1383 of file renderer_unittests.cc.

1384 {
1385 auto context = GetContext();
1386 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1387 GetContext()->GetResourceAllocator());
1388
1389 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1390 *context, {100, 100}, /*mip_count=*/1);
1391 EXPECT_EQ(render_target.GetDepthAttachment()
1392 ->texture->GetTextureDescriptor()
1393 .format,
1394 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1395 }

References impeller::RenderTarget::GetDepthAttachment().

## ◆ TEST_P() [459/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1211 of file renderer_unittests.cc.

1211 {
1212 using VS = BoxFadeVertexShader;
1213 using FS = BoxFadeFragmentShader;
1214 auto context = GetContext();
1215 ASSERT_TRUE(context);
1216 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1217 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1218 ASSERT_TRUE(desc.has_value());
1219
1220 // Vertex buffer.
1221 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1222 vertex_builder.SetLabel("Box");
1223 vertex_builder.AddVertices({
1224 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1225 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1226 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1227 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1228 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1229 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1230 });
1231 auto vertex_buffer =
1232 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1233 ASSERT_TRUE(vertex_buffer);
1234
1235 desc->SetSampleCount(SampleCount::kCount4);
1236 desc->SetStencilAttachmentDescriptors(std::nullopt);
1237
1238 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1239 auto boston = CreateTextureForFixture("boston.jpg");
1240 ASSERT_TRUE(bridge && boston);
1241 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1242 ASSERT_TRUE(sampler);
1243
1244 static bool mirror = false;
1245 static int stencil_reference_write = 0xFF;
1246 static int stencil_reference_read = 0x1;
1247 std::vector<uint8_t> stencil_contents;
1248 static int last_stencil_contents_reference_value = 0;
1249 static int current_front_compare =
1250 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1251 static int current_back_compare =
1252 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1253
1254 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
1255 context->GetIdleWaiter());
1256 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
1257 auto buffer = context->CreateCommandBuffer();
1258 if (!buffer) {
1259 return false;
1260 }
1261 buffer->SetLabel("Playground Command Buffer");
1262
1263 {
1264 // Configure the stencil attachment for the test.
1265 RenderTarget::AttachmentConfig stencil_config;
1266 stencil_config.load_action = LoadAction::kLoad;
1267 stencil_config.store_action = StoreAction::kDontCare;
1268 stencil_config.storage_mode = StorageMode::kHostVisible;
1269 render_target.SetupDepthStencilAttachments(
1270 *context, *context->GetResourceAllocator(),
1271 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1272 // Fill the stencil buffer with an checkerboard pattern.
1273 const auto target_width = render_target.GetRenderTargetSize().width;
1274 const auto target_height = render_target.GetRenderTargetSize().height;
1275 const size_t target_size = target_width * target_height;
1276 if (stencil_contents.size() != target_size ||
1277 last_stencil_contents_reference_value != stencil_reference_write) {
1278 stencil_contents.resize(target_size);
1279 last_stencil_contents_reference_value = stencil_reference_write;
1280 for (int y = 0; y < target_height; y++) {
1281 for (int x = 0; x < target_width; x++) {
1282 const auto index = y * target_width + x;
1283 const auto kCheckSize = 64;
1284 const auto value =
1285 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1286 stencil_reference_write;
1287 stencil_contents[index] = value;
1288 }
1289 }
1290 }
1291 if (!render_target.GetStencilAttachment()->texture->SetContents(
1292 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1293 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1294 return false;
1295 }
1296 auto pass = buffer->CreateRenderPass(render_target);
1297 if (!pass) {
1298 return false;
1299 }
1300 pass->SetLabel("Stencil Buffer");
1301 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1302 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1303 0xFF);
1304 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1305 0xFF);
1306 ImGui::Checkbox("Back face mode", &mirror);
1307 ImGui::ListBox("Front face compare function", &current_front_compare,
1308 CompareFunctionUI().labels(), CompareFunctionUI().size());
1309 ImGui::ListBox("Back face compare function", &current_back_compare,
1310 CompareFunctionUI().labels(), CompareFunctionUI().size());
1311 ImGui::End();
1312
1313 StencilAttachmentDescriptor front;
1314 front.stencil_compare =
1315 CompareFunctionUI().FunctionOf(current_front_compare);
1316 StencilAttachmentDescriptor back;
1317 back.stencil_compare =
1318 CompareFunctionUI().FunctionOf(current_back_compare);
1319 desc->SetStencilAttachmentDescriptors(front, back);
1320 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1321
1322 assert(pipeline && pipeline->IsValid());
1323
1324 pass->SetCommandLabel("Box");
1325 pass->SetPipeline(pipeline);
1326 pass->SetStencilReference(stencil_reference_read);
1327 pass->SetVertexBuffer(vertex_buffer);
1328
1329 VS::UniformBuffer uniforms;
1330 EXPECT_EQ(pass->GetOrthographicTransform(),
1331 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1332 uniforms.mvp = pass->GetOrthographicTransform() *
1333 Matrix::MakeScale(GetContentScale());
1334 if (mirror) {
1335 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1336 }
1337 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1338
1339 FS::FrameInfo frame_info;
1340 frame_info.current_time = GetSecondsElapsed();
1341 frame_info.cursor_position = GetCursorPosition();
1342 frame_info.window_size.x = GetWindowSize().width;
1343 frame_info.window_size.y = GetWindowSize().height;
1344
1345 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1346 FS::BindContents1(*pass, boston, sampler);
1347 FS::BindContents2(*pass, bridge, sampler);
1348 if (!pass->Draw().ok()) {
1349 return false;
1350 }
1351 pass->EncodeCommands();
1352 }
1353
1354 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1355 return false;
1356 }
1357 host_buffer->Reset();
1358 return true;
1359 };
1360 OpenPlaygroundHere(callback);
1361 }

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, VALIDATION_LOG, value, and x.

## ◆ TEST_P() [460/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 887 of file renderer_unittests.cc.

887 {
888 using VS = ImpellerVertexShader;
889 using FS = ImpellerFragmentShader;
890
891 auto context = GetContext();
892 auto pipeline_descriptor =
893 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
894 ASSERT_TRUE(pipeline_descriptor.has_value());
895 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
896 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
897 auto pipeline =
898 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
899 ASSERT_TRUE(pipeline && pipeline->IsValid());
900
901 auto blue_noise = CreateTextureForFixture("blue_noise.png");
902 SamplerDescriptor noise_sampler_desc;
903 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
904 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
905 raw_ptr<const Sampler> noise_sampler =
906 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
907
908 auto cube_map = CreateTextureCubeForFixture(
909 {"table_mountain_px.png", "table_mountain_nx.png",
910 "table_mountain_py.png", "table_mountain_ny.png",
911 "table_mountain_pz.png", "table_mountain_nz.png"});
912 raw_ptr<const Sampler> cube_map_sampler =
913 context->GetSamplerLibrary()->GetSampler({});
914 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
915 context->GetIdleWaiter());
916
917 SinglePassCallback callback = [&](RenderPass& pass) {
918 auto size = pass.GetRenderTargetSize();
919
920 pass.SetPipeline(pipeline);
921 pass.SetCommandLabel("Impeller SDF scene");
922 VertexBufferBuilder<VS::PerVertexData> builder;
923 builder.AddVertices({{Point()},
924 {Point(0, size.height)},
925 {Point(size.width, 0)},
926 {Point(size.width, 0)},
927 {Point(0, size.height)},
928 {Point(size.width, size.height)}});
929 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
930
931 VS::FrameInfo frame_info;
932 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
933 frame_info.mvp = pass.GetOrthographicTransform();
934 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
935
936 FS::FragInfo fs_uniform;
937 fs_uniform.texture_size = Point(size);
938 fs_uniform.time = GetSecondsElapsed();
939 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
940 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
941 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
942
943 pass.Draw().ok();
944 host_buffer->Reset();
945 return true;
946 };
947 OpenPlaygroundHere(callback);
948 }

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() [461/494]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1141 of file renderer_unittests.cc.

1141 {
1142 // Does not create index buffer if one is provided.
1143 using VS = BoxFadeVertexShader;
1144 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1145 vertex_builder.SetLabel("Box");
1146 vertex_builder.AddVertices({
1147 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1148 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1149 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1150 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1151 });
1152 vertex_builder.AppendIndex(0);
1153 vertex_builder.AppendIndex(1);
1154 vertex_builder.AppendIndex(2);
1155 vertex_builder.AppendIndex(1);
1156 vertex_builder.AppendIndex(2);
1157 vertex_builder.AppendIndex(3);
1158
1159 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1160 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1161 }

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() [462/494]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachedTextureGetsNewAttachmentConfig |
| ) |  |

Definition at line 122 of file render_target_cache_unittests.cc.

122 {
123 auto render_target_cache = RenderTargetCache(
124 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
125
126 render_target_cache.Start();
127 RenderTarget::AttachmentConfig color_attachment_config =
128 RenderTarget::kDefaultColorAttachmentConfig;
129 RenderTarget target1 = render_target_cache.CreateOffscreen(
130 *GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
131 render_target_cache.End();
132
133 render_target_cache.Start();
134 color_attachment_config.clear_color = Color::Red();
135 RenderTarget target2 = render_target_cache.CreateOffscreen(
136 *GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
137 render_target_cache.End();
138
139 ColorAttachment color1 = target1.GetColorAttachment(0);
140 ColorAttachment color2 = target2.GetColorAttachment(0);
141 // The second color attachment should reuse the first attachment's texture
142 // but with attributes from the second AttachmentConfig.
143 EXPECT_EQ(color2.texture, color1.texture);
144 EXPECT_EQ(color2.clear_color, Color::Red());
145 }

References impeller::RenderTarget::AttachmentConfig::clear_color, impeller::ColorAttachment::clear_color, impeller::RenderTarget::GetColorAttachment(), impeller::RenderTarget::kDefaultColorAttachmentConfig, impeller::Color::Red(), and impeller::Attachment::texture.

## ◆ TEST_P() [463/494]

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

Definition at line 52 of file render_target_cache_unittests.cc.

52 {
53 auto render_target_cache = RenderTargetCache(
54 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
55
56 render_target_cache.Start();
57 // Create two render targets of the same exact size/shape. Both should be
58 // marked as used this frame, so the cached data set will contain two.
59 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
60 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
61
62 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
63
64 render_target_cache.End();
65 render_target_cache.Start();
66
67 // Next frame, only create one texture. The set will still contain two,
68 // but one will be removed at the end of the frame.
69 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
70 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
71
72 render_target_cache.End();
73 EXPECT_EQ(render_target_cache.CachedTextureCount(), 1u);
74 }

## ◆ TEST_P() [464/494]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFramesWithKeepAlive |
| ) |  |

Definition at line 76 of file render_target_cache_unittests.cc.

76 {
77 auto render_target_cache = RenderTargetCache(
78 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/3);
79
80 render_target_cache.Start();
81 // Create two render targets of the same exact size/shape. Both should be
82 // marked as used this frame, so the cached data set will contain two.
83 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
84 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
85
86 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
87
88 render_target_cache.End();
89 render_target_cache.Start();
90
91 // The unused texture is kept alive until the keep alive countdown
92 // reaches 0.
93 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
94
95 for (auto i = 0; i < 3; i++) {
96 render_target_cache.Start();
97 render_target_cache.End();
98 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
99 }
100 // After the countdown has elapsed the texture is removed.
101 render_target_cache.Start();
102 render_target_cache.End();
103 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
104 }

## ◆ TEST_P() [465/494]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CreateWithEmptySize |
| ) |  |

Definition at line 147 of file render_target_cache_unittests.cc.

147 {
148 auto render_target_cache = RenderTargetCache(
149 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
150
151 render_target_cache.Start();
152 RenderTarget empty_target =
153 render_target_cache.CreateOffscreen(*GetContext(), {100, 0}, 1);
154 RenderTarget empty_target_msaa =
155 render_target_cache.CreateOffscreenMSAA(*GetContext(), {0, 0}, 1);
156 render_target_cache.End();
157
158 {
159 ScopedValidationDisable disable_validation;
160 EXPECT_FALSE(empty_target.IsValid());
161 EXPECT_FALSE(empty_target_msaa.IsValid());
162 }
163 }

References impeller::RenderTarget::IsValid().

## ◆ TEST_P() [466/494]

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

Definition at line 106 of file render_target_cache_unittests.cc.

106 {
107 ScopedValidationDisable disable;
108 auto allocator = std::make_shared<TestAllocator>();
109 auto render_target_cache =
110 RenderTargetCache(allocator, /*keep_alive_frame_count=*/0);
111
112 render_target_cache.Start();
113 allocator->should_fail = true;
114
115 auto render_target =
116 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
117
118 EXPECT_FALSE(render_target.IsValid());
119 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
120 }

## ◆ TEST_P() [467/494]

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() [468/494]

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() [469/494]

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() [470/494]

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() [471/494]

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() [472/494]

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() [473/494]

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() [474/494]

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() [475/494]

impeller::testing::TEST_P | ( | SwapchainTransientsMTLTest | ,
|  | CanAllocateSwapchainTextures |
| ) |  |

Definition at line 27 of file swapchain_transients_mtl_unittests.mm.

27 {
28 const auto& transients = std::make_shared<SwapchainTransientsMTL>(
29 GetContext()->GetResourceAllocator());
30
31 transients->SetSizeAndFormat({1, 1}, PixelFormat::kB8G8R8A8UNormInt);
32
33 auto resolve = transients->GetResolveTexture();
34 EXPECT_NE(resolve, nullptr);
35 EXPECT_NE(transients->GetMSAATexture(), nullptr);
36 EXPECT_NE(transients->GetDepthStencilTexture(), nullptr);
37
38 // Texture properties are correct for resolve.
39 EXPECT_EQ(resolve->GetTextureDescriptor().size, ISize(1, 1));
40 EXPECT_EQ(resolve->GetTextureDescriptor().format,
41 PixelFormat::kB8G8R8A8UNormInt);
42 EXPECT_EQ(resolve->GetTextureDescriptor().sample_count, SampleCount::kCount1);
43 EXPECT_EQ(resolve->GetTextureDescriptor().storage_mode,
44 StorageMode::kDevicePrivate);
45
46 // Texture properties are correct for MSAA.
47 auto msaa = transients->GetMSAATexture();
48 EXPECT_EQ(msaa->GetTextureDescriptor().size, ISize(1, 1));
49 EXPECT_EQ(msaa->GetTextureDescriptor().format,
50 PixelFormat::kB8G8R8A8UNormInt);
51 EXPECT_EQ(msaa->GetTextureDescriptor().sample_count, SampleCount::kCount4);
52 EXPECT_EQ(msaa->GetTextureDescriptor().storage_mode,
53 StorageMode::kDeviceTransient);
54
55 // Texture properties are correct for Depth+Stencil.
56 auto depth_stencil = transients->GetDepthStencilTexture();
57 EXPECT_EQ(depth_stencil->GetTextureDescriptor().size, ISize(1, 1));
58 EXPECT_EQ(depth_stencil->GetTextureDescriptor().format,
59 PixelFormat::kD32FloatS8UInt);
60 EXPECT_EQ(depth_stencil->GetTextureDescriptor().sample_count,
61 SampleCount::kCount4);
62 EXPECT_EQ(depth_stencil->GetTextureDescriptor().storage_mode,
63 StorageMode::kDeviceTransient);
64
65 // Textures are cached.
66 EXPECT_EQ(transients->GetResolveTexture(), resolve);
67
68 // Texture cache is invalidated when size changes.
69 transients->SetSizeAndFormat({2, 2}, PixelFormat::kB8G8R8A8UNormInt);
70 EXPECT_NE(resolve, transients->GetResolveTexture());
71 resolve = transients->GetResolveTexture();
72
73 // Texture cache is invalidated when pixel format changes.
74 transients->SetSizeAndFormat({2, 2}, PixelFormat::kB10G10R10A10XR);
75 EXPECT_NE(resolve, transients->GetResolveTexture());
76 }

References impeller::kB10G10R10A10XR, impeller::kB8G8R8A8UNormInt, impeller::kCount1, impeller::kCount4, impeller::kD32FloatS8UInt, impeller::kDevicePrivate, and impeller::kDeviceTransient.

## ◆ TEST_P() [476/494]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | MaintainsShape |
| ) |  |

Definition at line 166 of file text_contents_unittests.cc.

166 {
167 std::shared_ptr<TextFrame> text_frame =
168 MakeTextFrame("th", "ahem.ttf", /*font_size=*/50);
169
170 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
171 std::shared_ptr<GlyphAtlasContext> atlas_context =
172 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
173 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
174 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
175 ASSERT_TRUE(context && context->IsValid());
176 for (int i = 0; i <= 1000; ++i) {
177 Scalar font_scale = 0.440 + (i / 1000.0);
178 Rect position_rect[2];
179 Rect uv_rect[2];
180
181 {
182 GlyphAtlasPipeline::VertexShader::PerVertexData data[12];
183 std::shared_ptr<GlyphAtlas> atlas =
184 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
185 GlyphAtlas::Type::kAlphaBitmap, font_scale,
186 atlas_context, text_frame);
187 ISize texture_size = atlas->GetTexture()->GetSize();
188
189 TextContents::ComputeVertexData(
190 data, text_frame, font_scale,
191 /*entity_transform=*/Matrix::MakeScale({font_scale, font_scale, 1}),
192 /*offset=*/Vector2(0, 0),
193 /*glyph_properties=*/std::nullopt, atlas);
194 position_rect[0] = PerVertexDataPositionToRect(data);
195 uv_rect[0] = PerVertexDataUVToRect(data, texture_size);
196 position_rect[1] = PerVertexDataPositionToRect(data + 6);
197 uv_rect[1] = PerVertexDataUVToRect(data + 6, texture_size);
198 }
199 EXPECT_NEAR(GetAspectRatio(position_rect[1]), GetAspectRatio(uv_rect[1]),
200 0.001)
201 << i;
202 }
203 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [477/494]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleComputeVertexData |
| ) |  |

Definition at line 96 of file text_contents_unittests.cc.

96 {
97 #ifndef FML_OS_MACOSX
98 GTEST_SKIP() << "Results aren't stable across linux and macos.";
99 #endif
100
101 GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
102
103 std::shared_ptr<TextFrame> text_frame =
104 MakeTextFrame("1", "ahem.ttf", /*font_size=*/50);
105
106 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
107 std::shared_ptr<GlyphAtlasContext> atlas_context =
108 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
109 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
110 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
111 ASSERT_TRUE(context && context->IsValid());
112 std::shared_ptr<GlyphAtlas> atlas =
113 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
114 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
115 atlas_context, text_frame);
116
117 ISize texture_size = atlas->GetTexture()->GetSize();
118 TextContents::ComputeVertexData(data, text_frame, /*scale=*/1.0,
119 /*entity_transform=*/Matrix(),
120 /*offset=*/Vector2(0, 0),
121 /*glyph_properties=*/std::nullopt, atlas);
122
123 Rect position_rect = PerVertexDataPositionToRect(data);
124 Rect uv_rect = PerVertexDataUVToRect(data, texture_size);
125 // The -1 offset comes from Skia in `ComputeGlyphSize`. So since the font size
126 // is 50, the math appears to be to get back a 50x50 rect and apply 1 pixel
127 // of padding.
128 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
129 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
130 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [478/494]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleComputeVertexData2x |
| ) |  |

Definition at line 132 of file text_contents_unittests.cc.

132 {
133 #ifndef FML_OS_MACOSX
134 GTEST_SKIP() << "Results aren't stable across linux and macos.";
135 #endif
136
137 GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
138
139 std::shared_ptr<TextFrame> text_frame =
140 MakeTextFrame("1", "ahem.ttf", /*font_size=*/50);
141
142 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
143 std::shared_ptr<GlyphAtlasContext> atlas_context =
144 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
145 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
146 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
147 ASSERT_TRUE(context && context->IsValid());
148 Scalar font_scale = 2.f;
149 std::shared_ptr<GlyphAtlas> atlas = CreateGlyphAtlas(
150 *GetContext(), context.get(), *host_buffer,
151 GlyphAtlas::Type::kAlphaBitmap, font_scale, atlas_context, text_frame);
152
153 ISize texture_size = atlas->GetTexture()->GetSize();
154 TextContents::ComputeVertexData(
155 data, text_frame, font_scale,
156 /*entity_transform=*/Matrix::MakeScale({font_scale, font_scale, 1}),
157 /*offset=*/Vector2(0, 0),
158 /*glyph_properties=*/std::nullopt, atlas);
159
160 Rect position_rect = PerVertexDataPositionToRect(data);
161 Rect uv_rect = PerVertexDataUVToRect(data, texture_size);
162 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -81, 102, 102));
163 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 102, 102));
164 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeScale(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [479/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanConvertTextBlob |
| ) |  |

Definition at line 62 of file typographer_unittests.cc.

62 {
63 SkFont font = flutter::testing::CreateTestFontOfSize(12);
64 auto blob = SkTextBlob::MakeFromString(
65 "the quick brown fox jumped over the lazy dog.", font);
66 ASSERT_TRUE(blob);
67 auto frame = MakeTextFrameFromTextBlobSkia(blob);
68 ASSERT_EQ(frame->GetRunCount(), 1u);
69 for (const auto& run : frame->GetRuns()) {
70 ASSERT_TRUE(run.IsValid());
71 ASSERT_EQ(run.GetGlyphCount(), 45u);
72 }
73 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [480/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateGlyphAtlas |
| ) |  |

Definition at line 80 of file typographer_unittests.cc.

80 {
81 auto context = TypographerContextSkia::Make();
82 auto atlas_context =
83 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
84 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
85 GetContext()->GetIdleWaiter());
86 ASSERT_TRUE(context && context->IsValid());
87 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
88 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
89 ASSERT_TRUE(blob);
90 auto atlas =
91 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
92 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
93 MakeTextFrameFromTextBlobSkia(blob));
94
95 ASSERT_NE(atlas, nullptr);
96 ASSERT_NE(atlas->GetTexture(), nullptr);
97 ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
98 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
99
100 std::optional<impeller::ScaledFont> first_scaled_font;
101 std::optional<impeller::SubpixelGlyph> first_glyph;
102 Rect first_rect;
103 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
104 const SubpixelGlyph& glyph,
105 const Rect& rect) -> bool {
106 first_scaled_font = scaled_font;
107 first_glyph = glyph;
108 first_rect = rect;
109 return false;
110 });
111
112 ASSERT_TRUE(first_scaled_font.has_value());
113 ASSERT_TRUE(atlas
114 ->FindFontGlyphBounds(
115 {first_scaled_font.value(), first_glyph.value()})
116 .has_value());
117 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [481/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateRenderContext |
| ) |  |

Definition at line 75 of file typographer_unittests.cc.

75 {
76 auto context = TypographerContextSkia::Make();
77 ASSERT_TRUE(context && context->IsValid());
78 }

References impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [482/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasIsRecycledIfUnchanged |
| ) |  |

Definition at line 180 of file typographer_unittests.cc.

180 {
181 auto context = TypographerContextSkia::Make();
182 auto atlas_context =
183 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
184 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
185 GetContext()->GetIdleWaiter());
186 ASSERT_TRUE(context && context->IsValid());
187 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
188 auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
189 ASSERT_TRUE(blob);
190 auto atlas =
191 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
192 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
193 MakeTextFrameFromTextBlobSkia(blob));
194 ASSERT_NE(atlas, nullptr);
195 ASSERT_NE(atlas->GetTexture(), nullptr);
196 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
197
198 // now attempt to re-create an atlas with the same text blob.
199
200 auto next_atlas =
201 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
202 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
203 MakeTextFrameFromTextBlobSkia(blob));
204 ASSERT_EQ(atlas, next_atlas);
205 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
206 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [483/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledIfUnchanged |
| ) |  |

Definition at line 256 of file typographer_unittests.cc.

256 {
257 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
258 GetContext()->GetIdleWaiter());
259 auto context = TypographerContextSkia::Make();
260 auto atlas_context =
261 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
262 ASSERT_TRUE(context && context->IsValid());
263 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
264 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
265 ASSERT_TRUE(blob);
266 auto atlas =
267 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
268 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
269 MakeTextFrameFromTextBlobSkia(blob));
270 auto old_packer = atlas_context->GetRectPacker();
271
272 ASSERT_NE(atlas, nullptr);
273 ASSERT_NE(atlas->GetTexture(), nullptr);
274 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
275
276 auto* first_texture = atlas->GetTexture().get();
277
278 // Now create a new glyph atlas with a nearly identical blob.
279
280 auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
281 auto next_atlas =
282 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
283 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
284 MakeTextFrameFromTextBlobSkia(blob2));
285 ASSERT_EQ(atlas, next_atlas);
286 auto* second_texture = next_atlas->GetTexture().get();
287
288 auto new_packer = atlas_context->GetRectPacker();
289
290 ASSERT_EQ(second_texture, first_texture);
291 ASSERT_EQ(old_packer, new_packer);
292 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [484/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureWillGrowTilMaxTextureSize |
| ) |  |

Definition at line 425 of file typographer_unittests.cc.

425 {
426 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
427 GTEST_SKIP() << "Atlas growth isn't supported for OpenGLES currently.";
428 }
429
430 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
431 GetContext()->GetIdleWaiter());
432 auto context = TypographerContextSkia::Make();
433 auto atlas_context =
434 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
435 ASSERT_TRUE(context && context->IsValid());
436 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
437 auto blob = SkTextBlob::MakeFromString("A", sk_font);
438 ASSERT_TRUE(blob);
439 auto atlas =
440 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
441 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
442 MakeTextFrameFromTextBlobSkia(blob));
443 // Continually append new glyphs until the glyph size grows to the maximum.
444 // Note that the sizes here are more or less experimentally determined, but
445 // the important expectation is that the atlas size will shrink again after
446 // growing to the maximum size.
447 constexpr ISize expected_sizes[13] = {
448 {4096, 4096}, //
449 {4096, 4096}, //
450 {4096, 8192}, //
451 {4096, 8192}, //
452 {4096, 8192}, //
453 {4096, 8192}, //
454 {4096, 16384}, //
455 {4096, 16384}, //
456 {4096, 16384}, //
457 {4096, 16384}, //
458 {4096, 16384}, //
459 {4096, 16384}, //
460 {4096, 4096} // Shrinks!
461 };
462
463 SkFont sk_font_small = flutter::testing::CreateTestFontOfSize(10);
464
465 for (int i = 0; i < 13; i++) {
466 SkTextBlobBuilder builder;
467
468 auto add_char = [&](const SkFont& sk_font, char c) {
469 int count = sk_font.countText(&c, 1, SkTextEncoding::kUTF8);
470 auto buffer = builder.allocRunPos(sk_font, count);
471 sk_font.textToGlyphs(&c, 1, SkTextEncoding::kUTF8, buffer.glyphs, count);
472 sk_font.getPos(buffer.glyphs, count, buffer.points(), {0, 0});
473 };
474
475 SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
476 add_char(sk_font, 'A');
477 add_char(sk_font_small, 'B');
478 auto blob = builder.make();
479
480 atlas =
481 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
482 GlyphAtlas::Type::kAlphaBitmap, 50 + i, atlas_context,
483 MakeTextFrameFromTextBlobSkia(blob));
484 ASSERT_TRUE(!!atlas);
485 EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
486 expected_sizes[i]);
487 }
488
489 // The final atlas should contain both the "A" glyph (which was not present
490 // in the previous atlas) and the "B" glyph (which existed in the previous
491 // atlas).
492 ASSERT_EQ(atlas->GetGlyphCount(), 2u);
493 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [485/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithLotsOfdUniqueGlyphSize |
| ) |  |

Definition at line 208 of file typographer_unittests.cc.

208 {
209 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
210 GetContext()->GetIdleWaiter());
211 auto context = TypographerContextSkia::Make();
212 auto atlas_context =
213 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
214 ASSERT_TRUE(context && context->IsValid());
215
216 const char* test_string =
217 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
218 "2134567890-=!@#$%^&*()_+"
219 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›ﬁﬂ‡°·‚—±Œ„´‰Á¨Ø∏”’/"
220 "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
221
222 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
223 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
224 ASSERT_TRUE(blob);
225
226 size_t size_count = 8;
227 std::vector<std::shared_ptr<TextFrame>> frames;
228 for (size_t index = 0; index < size_count; index += 1) {
229 frames.push_back(MakeTextFrameFromTextBlobSkia(blob));
230 frames.back()->SetPerFrameData(0.6 * index, {0, 0}, Matrix(), {});
231 };
232 auto atlas =
233 context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
234 *host_buffer, atlas_context, frames);
235 ASSERT_NE(atlas, nullptr);
236 ASSERT_NE(atlas->GetTexture(), nullptr);
237
238 std::set<uint16_t> unique_glyphs;
239 std::vector<uint16_t> total_glyphs;
240 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
241 const SubpixelGlyph& glyph, const Rect& rect) {
242 unique_glyphs.insert(glyph.glyph.index);
243 total_glyphs.push_back(glyph.glyph.index);
244 return true;
245 });
246
247 // These numbers may be different due to subpixel positions.
248 EXPECT_LE(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
249 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
250
251 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
252 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
253 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
254 }

References impeller::HostBuffer::Create(), impeller::SubpixelGlyph::glyph, impeller::Glyph::index, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [486/494]

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 GetContext()->GetIdleWaiter());
165 ASSERT_TRUE(context && context->IsValid());
166 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
167 auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
168 ASSERT_TRUE(blob);
169 auto atlas =
170 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
171 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
172 MakeTextFrameFromTextBlobSkia(blob));
173 ASSERT_NE(atlas, nullptr);
174 ASSERT_NE(atlas->GetTexture(), nullptr);
175
176 EXPECT_EQ(atlas->GetTexture()->GetSize().width, 4096u);
177 EXPECT_EQ(atlas->GetTexture()->GetSize().height, 1024u);
178 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [487/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsIgnoredForNonEmojiFonts |
| ) |  |

Definition at line 329 of file typographer_unittests.cc.

329 {
330 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
331 GetContext()->GetIdleWaiter());
332 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
333 sk_sp<SkTypeface> typeface =
334 font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
335 SkFont sk_font(typeface, 0.5f);
336
337 auto context = TypographerContextSkia::Make();
338 auto atlas_context =
339 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
340
341 // Create two frames with the same character and a different color, but as a
342 // non-emoji font the text frame constructor will ignore it.
343 auto frame =
344 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
345 auto frame_2 =
346 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
347 std::vector<std::optional<GlyphProperties>> properties = {
348 GlyphProperties{},
349 GlyphProperties{},
350 };
351
352 auto next_atlas =
353 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
354 GlyphAtlas::Type::kColorBitmap, 1.0f, atlas_context,
355 {frame, frame_2}, properties);
356
357 EXPECT_EQ(next_atlas->GetGlyphCount(), 1u);
358 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [488/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsPartOfCacheKey |
| ) |  |

Definition at line 294 of file typographer_unittests.cc.

294 {
295 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
296 GetContext()->GetIdleWaiter());
297 #if FML_OS_MACOSX
298 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
299 #else
300 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
301 #endif
302 ASSERT_TRUE(mapping);
303 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
304 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
305
306 auto context = TypographerContextSkia::Make();
307 auto atlas_context =
308 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
309
310 // Create two frames with the same character and a different color, expect
311 // that it adds a character.
312 auto frame = MakeTextFrameFromTextBlobSkia(
313 SkTextBlob::MakeFromString("😂", emoji_font));
314 auto frame_2 = MakeTextFrameFromTextBlobSkia(
315 SkTextBlob::MakeFromString("😂", emoji_font));
316 std::vector<std::optional<GlyphProperties>> properties = {
317 GlyphProperties{.color = Color::Red()},
318 GlyphProperties{.color = Color::Blue()},
319 };
320
321 auto next_atlas =
322 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
323 GlyphAtlas::Type::kColorBitmap, 1.0f, atlas_context,
324 {frame, frame_2}, properties);
325
326 EXPECT_EQ(next_atlas->GetGlyphCount(), 2u);
327 }

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() [489/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | InvalidAtlasForcesRepopulation |
| ) |  |

Definition at line 615 of file typographer_unittests.cc.

615 {
616 SkFont font = flutter::testing::CreateTestFontOfSize(12);
617 auto blob = SkTextBlob::MakeFromString(
618 "the quick brown fox jumped over the lazy dog.", font);
619 ASSERT_TRUE(blob);
620 auto frame = MakeTextFrameFromTextBlobSkia(blob);
621
622 EXPECT_FALSE(frame->IsFrameComplete());
623
624 auto context = TypographerContextSkia::Make();
625 auto atlas_context =
626 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
627 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
628 GetContext()->GetIdleWaiter());
629
630 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
631 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
632 atlas_context, frame);
633
634 // The glyph position in the atlas was not known when this value
635 // was recorded. It is marked as a placeholder.
636 EXPECT_TRUE(frame->IsFrameComplete());
637 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
638 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
639 // OpenGLES must always increase the atlas backend if the texture grows.
640 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
641 } else {
642 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
643 }
644
645 auto second_context = TypographerContextSkia::Make();
646 auto second_atlas_context =
647 second_context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
648
649 EXPECT_FALSE(second_atlas_context->GetGlyphAtlas()->IsValid());
650
651 atlas = CreateGlyphAtlas(*GetContext(), second_context.get(), *host_buffer,
652 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
653 second_atlas_context, frame);
654
655 EXPECT_TRUE(second_atlas_context->GetGlyphAtlas()->IsValid());
656 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [490/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | LazyAtlasTracksColor |
| ) |  |

Definition at line 119 of file typographer_unittests.cc.

119 {
120 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
121 GetContext()->GetIdleWaiter());
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}, Matrix(), {});
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}, Matrix(), {});
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() [491/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | RectanglePackerAddsNonoverlapingRectangles |
| ) |  |

Definition at line 360 of file typographer_unittests.cc.

360 {
361 auto packer = RectanglePacker::Factory(200, 100);
362 ASSERT_NE(packer, nullptr);
363 ASSERT_EQ(packer->PercentFull(), 0);
364
365 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
366
367 IPoint16 first_output = {-1, -1}; // Fill with sentinel values
368 ASSERT_TRUE(packer->AddRect(20, 20, &first_output));
369 // Make sure the rectangle is placed such that it is inside the bounds of
370 // the packer's area.
371 const SkIRect first_rect =
372 SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
373 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
374
375 // Initial area was 200 x 100 = 20_000
376 // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
377 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.02));
378
379 IPoint16 second_output = {-1, -1};
380 ASSERT_TRUE(packer->AddRect(140, 90, &second_output));
381 const SkIRect second_rect =
382 SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
383 // Make sure the rectangle is placed such that it is inside the bounds of
384 // the packer's area but not in the are of the first rectangle.
385 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
386 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
387
388 // We added another 90 x 140 = 12_600 units, now taking us to 13_000
389 // 13_000 / 20_000 == 0.65 == 65%
390 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
391
392 // There's enough area to add this rectangle, but no space big enough for
393 // the 50 units of width.
394 IPoint16 output;
395 ASSERT_FALSE(packer->AddRect(50, 50, &output));
396 // Should be unchanged.
397 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
398
399 packer->Reset();
400 // Should be empty now.
401 ASSERT_EQ(packer->PercentFull(), 0);
402 }

References impeller::RectanglePacker::Factory(), NumberNear(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ TEST_P() [492/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameAtlasGenerationTracksState |
| ) |  |

Definition at line 563 of file typographer_unittests.cc.

563 {
564 SkFont font = flutter::testing::CreateTestFontOfSize(12);
565 auto blob = SkTextBlob::MakeFromString(
566 "the quick brown fox jumped over the lazy dog.", font);
567 ASSERT_TRUE(blob);
568 auto frame = MakeTextFrameFromTextBlobSkia(blob);
569
570 EXPECT_FALSE(frame->IsFrameComplete());
571
572 auto context = TypographerContextSkia::Make();
573 auto atlas_context =
574 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
575 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
576 GetContext()->GetIdleWaiter());
577
578 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
579 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
580 atlas_context, frame);
581
582 // The glyph position in the atlas was not known when this value
583 // was recorded. It is marked as a placeholder.
584 EXPECT_TRUE(frame->IsFrameComplete());
585 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
586 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
587 // OpenGLES must always increase the atlas backend if the texture grows.
588 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
589 } else {
590 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
591 }
592
593 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
594 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
595 atlas_context, frame);
596
597 // The second time the glyph is rendered, the bounds are correcly known.
598 EXPECT_TRUE(frame->IsFrameComplete());
599 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
600 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
601 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
602 } else {
603 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
604 }
605
606 // Force increase the generation.
607 atlas_context->GetGlyphAtlas()->SetAtlasGeneration(2u);
608 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
609 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
610 atlas_context, frame);
611
612 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 2u);
613 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [493/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInitialBoundsArePlaceholder |
| ) |  |

Definition at line 495 of file typographer_unittests.cc.

495 {
496 SkFont font = flutter::testing::CreateTestFontOfSize(12);
497 auto blob = SkTextBlob::MakeFromString(
498 "the quick brown fox jumped over the lazy dog.", font);
499 ASSERT_TRUE(blob);
500 auto frame = MakeTextFrameFromTextBlobSkia(blob);
501
502 EXPECT_FALSE(frame->IsFrameComplete());
503
504 auto context = TypographerContextSkia::Make();
505 auto atlas_context =
506 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
507 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
508 GetContext()->GetIdleWaiter());
509
510 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
511 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
512 atlas_context, frame);
513
514 // The glyph position in the atlas was not known when this value
515 // was recorded. It is marked as a placeholder.
516 EXPECT_TRUE(frame->IsFrameComplete());
517 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
518
519 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
520 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
521 atlas_context, frame);
522
523 // The second time the glyph is rendered, the bounds are correcly known.
524 EXPECT_TRUE(frame->IsFrameComplete());
525 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
526 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [494/494]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInvalidationWithScale |
| ) |  |

Definition at line 528 of file typographer_unittests.cc.

528 {
529 SkFont font = flutter::testing::CreateTestFontOfSize(12);
530 auto blob = SkTextBlob::MakeFromString(
531 "the quick brown fox jumped over the lazy dog.", font);
532 ASSERT_TRUE(blob);
533 auto frame = MakeTextFrameFromTextBlobSkia(blob);
534
535 EXPECT_FALSE(frame->IsFrameComplete());
536
537 auto context = TypographerContextSkia::Make();
538 auto atlas_context =
539 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
540 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
541 GetContext()->GetIdleWaiter());
542
543 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
544 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
545 atlas_context, frame);
546
547 // The glyph position in the atlas was not known when this value
548 // was recorded. It is marked as a placeholder.
549 EXPECT_TRUE(frame->IsFrameComplete());
550 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
551
552 // Change the scale and the glyph data will still be a placeholder, as the
553 // old data is no longer valid.
554 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
555 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/2.0f,
556 atlas_context, frame);
557
558 // The second time the glyph is rendered, the bounds are correcly known.
559 EXPECT_TRUE(frame->IsFrameComplete());
560 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
561 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ toColor()

flutter::DlColor impeller::testing::toColor | ( | const float * | components | ) |

Definition at line 41 of file dl_unittests.cc.

41 {
42 return flutter::DlColor(Color::ToIColor(
43 Color(components[0], components[1], components[2], components[3])));
44 }

References impeller::Color::ToIColor().

Referenced by TEST_P().

## Variable Documentation

## ◆ golden_cubic_and_quad_points

std::vector<Point> impeller::testing::golden_cubic_and_quad_points

Definition at line 16 of file golden_paths.h.

## ◆ kFontFixture

constexpr std::string_view impeller::testing::kFontFixture
| static constexpr

Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 246 of file aiks_dl_text_unittests.cc.

Referenced by TEST_P().

## ◆ kMagicFailingAllocation

constexpr const size_t impeller::testing::kMagicFailingAllocation = 1024000 * 2
| static constexpr

Definition at line 191 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 587 of file aiks_dl_blur_unittests.cc.

impeller::testing::kMagicFailingAllocation
static constexpr const size_t kMagicFailingAllocation
Definition: host_buffer_unittests.cc:191
impeller::ISize
ISize64 ISize
Definition: size.h:174
_BLEND_MODE_RESULT_CHECK
#define _BLEND_MODE_RESULT_CHECK(blend_mode)
Definition: geometry_unittests.cc:1686
NumberNear
bool NumberNear(double a, double b)
Definition: geometry_asserts.h:18
impeller::MipFilter::kBase
@ kBase
The texture is sampled as if it only had a single mipmap level.
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:39
impeller::PipelineRef
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition: pipeline.h:86
ASSERT_COLOR_NEAR
#define ASSERT_COLOR_NEAR(a, b)
Definition: geometry_asserts.h:192
impeller::kFloat
@ kFloat
Definition: runtime_types.h:25
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19
impeller::k1OverSqrt2
constexpr float k1OverSqrt2
Definition: constants.h:50
impeller::testing::CanBatchSubmitTest
bool CanBatchSubmitTest(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:70
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1206
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:311
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::PixelFormatToString
constexpr const char * PixelFormatToString(PixelFormat format)
Definition: formats.h:140
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::skia_conversions::IsNearlySimpleRRect
bool IsNearlySimpleRRect(const SkRRect &rr)
Like SkRRect.isSimple, but allows the corners to differ by kEhCloseEnough.
Definition: skia_conversions.cc:22
impeller::TPoint::Ceil
constexpr TPoint Ceil() const
Definition: point.h:196
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1189
impeller::kSqrt2
constexpr float kSqrt2
Definition: constants.h:47
uvs
Quad uvs
Definition: gaussian_blur_filter_contents.cc:205
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:116
impeller::testing::swap_nan
static constexpr Point swap_nan(const Point &point, int index)
Definition: rect_unittests.cc:1350
impeller::skia_conversions::ToSize
Size ToSize(const SkPoint &point)
Definition: skia_conversions.cc:85
impeller::BlendMode
BlendMode
Definition: color.h:58
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
impeller::testing::CanUsePrimitiveRestartSubmitTest
bool CanUsePrimitiveRestartSubmitTest(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:97
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::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:292
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::MebiBytes
AllocationSize< 1 '024u *1 '024u > MebiBytes
Definition: allocation_size.h:158
value
int32_t value
Definition: dl_golden_unittests.cc:444
impeller::WorkaroundsVK::batch_submit_command_buffer_timeout
bool batch_submit_command_buffer_timeout
Definition: workarounds_vk.h:24
impeller::DlPath
flutter::DlPath DlPath
Definition: dl_dispatcher.h:28
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:64
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:41
impeller::VS
GlyphAtlasPipeline::VertexShader VS
Definition: text_contents.cc:25
impeller::TPoint::Min
constexpr TPoint Min(const TPoint &p) const
Definition: point.h:186
impeller::MipFilter
MipFilter
Options for selecting and filtering between mipmap levels.
Definition: formats.h:425
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:19
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:165
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:1336
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:26
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:89
impeller::UintPoint32
TPoint< uint32_t > UintPoint32
Definition: point.h:330
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16
padding
Vector2 padding
The halo padding in source space.
Definition: gaussian_blur_filter_contents.cc:86
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:152
impeller::Size
TSize< Scalar > Size
Definition: size.h:171
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
x
int32_t x
Definition: dl_golden_unittests.cc:443
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:33
stroke_width
const Scalar stroke_width
Definition: stroke_path_geometry.cc:312
impeller::GibiBytes
AllocationSize< 1 '024u *1 '024u *1 '024u > GibiBytes
Definition: allocation_size.h:159
impeller::GetWorkaroundsFromDriverInfo
WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK &driver_info)
Definition: workarounds_vk.cc:10
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:319
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::MinMagFilter::kNearest
@ kNearest
Select nearest to the sample point. Most widely supported.
impeller::TPoint::Floor
constexpr TPoint Floor() const
Definition: point.h:194
impeller::skia_conversions::ToBlendMode
BlendMode ToBlendMode(flutter::DlBlendMode mode)
Definition: skia_conversions.cc:176
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
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< std::optional< GlyphProperties >> &properties)
Definition: typographer_unittests.cc:45
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:606
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::kPhi
constexpr float kPhi
Definition: constants.h:53
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:121
impeller::kPointArenaSize
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
Definition: tessellator.h:22
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:1199
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1579
EXPECT_MATRIX_NEAR
#define EXPECT_MATRIX_NEAR(a, b)
Definition: geometry_asserts.h:201
impeller::MipFilter::kLinear
@ kLinear
Sample from the two nearest mip levels and linearly interpolate.
impeller::testing::flip_lr
static constexpr R flip_lr(R rect)
Definition: rect_unittests.cc:1324
impeller::testing::CanUseMipgeneration
bool CanUseMipgeneration(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:126
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:214
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::TPoint::Max
constexpr TPoint Max(const TPoint &p) const
Definition: point.h:190
impeller::DlRect
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:15
type
GLenum type
Definition: blit_command_gles.cc:151
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::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1596
_BLEND_MODE_NAME_CHECK
#define _BLEND_MODE_NAME_CHECK(blend_mode)
Definition: geometry_unittests.cc:1704
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:792
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:27
impeller::skia_conversions::ToPoint
Point ToPoint(const SkPoint &point)
Definition: skia_conversions.cc:81
impeller::TSize::width
Type width
Definition: size.h:28
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::WorkaroundsVK::slow_primitive_restart_performance
bool slow_primitive_restart_performance
Definition: workarounds_vk.h:18
impeller::ContentContextOptions::primitive_type
PrimitiveType primitive_type
Definition: content_context.h:336
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::testing::CanUseFramebufferFetch
bool CanUseFramebufferFetch(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:196
impeller::GenerateBlurInfo
KernelSamples GenerateBlurInfo(BlurParameters parameters)
Definition: gaussian_blur_filter_contents.cc:907
impeller::Close
void Close(PathBuilder *builder)
Definition: tessellator.cc:38
impeller::MinMagFilter::kLinear
@ kLinear
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
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::shared_ptr< TextFrame > &frame)
Definition: typographer_unittests.cc:32
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:25
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::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
impeller::MyMaskBits
MyMaskBits
Definition: base_unittests.cc:13
ASSERT_VECTOR3_NEAR
#define ASSERT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:194
impeller::DeviceBufferDescriptor::readback
bool readback
Definition: device_buffer_descriptor.h:19
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:246
impeller::GetAdrenoVersion
AdrenoGPU GetAdrenoVersion(std::string_view version)
Definition: driver_info_vk.cc:108
scale
const Scalar scale
Definition: stroke_path_geometry.cc:316
blur_radius
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Definition: gaussian_blur_filter_contents.cc:84
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:954
impeller::WorkaroundsVK::input_attachment_self_dependency_broken
bool input_attachment_self_dependency_broken
Definition: workarounds_vk.h:28
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:795
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:1249
impeller::DlRoundRect
flutter::DlRoundRect DlRoundRect
Definition: dl_dispatcher.h:27
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::MinMagFilter
MinMagFilter
Describes how the texture should be sampled when the texture is being shrunk (minified) or expanded (...
Definition: formats.h:415
impeller::TSize::MipCount
constexpr size_t MipCount() const
Definition: size.h:140
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:1330
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:23
impeller::FS
GlyphAtlasPipeline::FragmentShader FS
Definition: text_contents.cc:26
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:144
impeller::testing::CreateTestCanvas
std::unique_ptr< Canvas > CreateTestCanvas(ContentContext &context, std::optional< Rect > cull_rect=std::nullopt, bool requires_readback=false)
Definition: canvas_unittests.cc:24
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:19
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::WorkaroundsVK::broken_mipmap_generation
bool broken_mipmap_generation
Definition: workarounds_vk.h:36
impeller::BufferResource
Resource< BufferView > BufferResource
Definition: command.h:54
impeller::testing::IsBadVersionTest
bool IsBadVersionTest(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:52